为啥我的 Spring 应用程序使用 @RestController 而不是 @Controller

Posted

技术标签:

【中文标题】为啥我的 Spring 应用程序使用 @RestController 而不是 @Controller【英文标题】:Why is my Spring application working with @RestController but not with @Controller为什么我的 Spring 应用程序使用 @RestController 而不是 @Controller 【发布时间】:2021-09-10 07:27:40 【问题描述】:

我正在学习有关 Spring 应用程序的教程,其中讲师正在构建一个基本的 Spring MVC 应用程序。讲师使用的是没有构建管理器的 Eclipse,但我使用的是带有 Gradle 的 IntelliJ Ultimate。我不确定这是否重要,但我包括保持透明。

在第一个项目中,讲师创建了一个如下所示的应用。

package com.example.springdemo.mvc;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.Controller;

@Controller
public class HomeController 

    @RequestMapping("/")
    public String showPage()
        return "main-menu";
    

当我运行项目时,我得到一个白标签错误页面。

但是,当我使用@RestController 而不是@Controller 运行程序时,它可以正常工作。讲师没有检查@RestController,我更愿意像讲师那样关注项目,但我所做的似乎没有任何效果?

我已经阅读了this page here,但它只是说我不需要@ResponseBody 注释,我的导师也没有使用它。这是因为不同的IDE吗?或者可能与部署自动化软件有关?还是完全不同的东西?我该怎么做才能让@Controller 注解在教师使用它时发挥作用?

编辑:

我刚刚注意到我的代码在使用@RestController 运行时,只在页面上显示“主菜单”字样。我正在尝试加载一个名为“main-menu.jsp”的页面。

这是我的文件夹结构

文件 spring-mvc-demo-servlet 包含以下 bean 代码:

<bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

编辑 2:

为了启动程序,我使用的是 IntelliJ 自动生成的 main 方法。

SpringMvcDemoApplication.java

package com.example.springdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication()
public class SpringMvcDemoApplication 

    public static void main(String[] args) 
        SpringApplication.run(SpringMvcDemoApplication.class, args);
    

我的 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">

    <display-name>spring-mvc-demo</display-name>

    <absolute-ordering />

    <!-- Spring MVC Configs -->

    <!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-mvc-demo-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

和spring-mvc-demo-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- Step 3: Add support for component scanning -->
    <context:component-scan base-package="com.example.springdemo" />

    <!-- Step 4: Add support for conversion, formatting and validation support -->
    <mvc:annotation-driven/>

    <!-- Step 5: Define Spring MVC view resolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="\WEB-INF\view" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

我的应用程序.properties

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

编辑 3:

这是我的错误堆栈 strace:

2021-06-27 17:21:17.573 DEBUG 7824 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : GET "/", parameters=
2021-06-27 17:21:17.573 DEBUG 7824 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.springdemo.HomeController#showPage()
2021-06-27 17:21:17.574 DEBUG 7824 --- [nio-8080-exec-4] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8]
2021-06-27 17:21:17.575 DEBUG 7824 --- [nio-8080-exec-4] o.s.w.servlet.view.InternalResourceView  : View name 'main-menu', model 
2021-06-27 17:21:17.575 DEBUG 7824 --- [nio-8080-exec-4] o.s.w.servlet.view.InternalResourceView  : Forwarding to [main-menu]
2021-06-27 17:21:17.575 DEBUG 7824 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : "FORWARD" dispatch for GET "/main-menu", parameters=
2021-06-27 17:21:17.576 DEBUG 7824 --- [nio-8080-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/], Classpath [resources/], Classpath [static/], Classpath [public/], ServletContext [/]]
2021-06-27 17:21:17.582 DEBUG 7824 --- [nio-8080-exec-4] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found
2021-06-27 17:21:17.582 DEBUG 7824 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Exiting from "FORWARD" dispatch, status 404
2021-06-27 17:21:17.583 DEBUG 7824 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
2021-06-27 17:21:17.583 DEBUG 7824 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters=
2021-06-27 17:21:17.583 DEBUG 7824 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2021-06-27 17:21:17.585 DEBUG 7824 --- [nio-8080-exec-4] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2021-06-27 17:21:17.586 DEBUG 7824 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 404

编辑 4:

按照@chrylis 的建议,我已经使用 Thymeleaf 重建了项目。我仍然收到错误,但堆栈不同。这是新堆栈。

2021-06-27 20:51:15.304 ERROR 42244 --- [nio-8080-exec-1] org.thymeleaf.TemplateEngine             : [THYMELEAF][http-nio-8080-exec-1] Exception processing template "main-menu": Error resolving template [main-menu], template might not exist or might not be accessible by any of the configured Template Resolvers

org.thymeleaf.exceptions.TemplateInputException: Error resolving template [main-menu], template might not exist or might not be accessible by any of the configured Template Resolvers
    at org.thymeleaf.engine.TemplateManager.resolveTemplate(TemplateManager.java:869) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:607) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) [thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) [thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366) [thymeleaf-spring5-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190) [thymeleaf-spring5-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1396) [spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1141) [spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080) [spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) [spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.3.8.jar:5.3.8]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) [tomcat-embed-core-9.0.48.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.3.8.jar:5.3.8]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) [tomcat-embed-core-9.0.48.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-embed-websocket-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_291]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_291]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_291]

2021-06-27 20:51:15.307 ERROR 42244 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving template [main-menu], template might not exist or might not be accessible by any of the configured Template Resolvers] with root cause

org.thymeleaf.exceptions.TemplateInputException: Error resolving template [main-menu], template might not exist or might not be accessible by any of the configured Template Resolvers
    at org.thymeleaf.engine.TemplateManager.resolveTemplate(TemplateManager.java:869) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:607) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366) ~[thymeleaf-spring5-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190) ~[thymeleaf-spring5-3.0.12.RELEASE.jar:3.0.12.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1396) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1141) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.48.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.48.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_291]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_291]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_291]

编辑 5:

回到我原来的构建,但摆脱了 web.xml,正如用户 @Asmin 所建议的那样。我似乎得到了更好的堆栈跟踪,现在表明它正在尝试打开名为 main-menu.jsp 的文件。但是,它说找不到资源。我尝试将spring.mvc.view.prefix 更改为读取为

spring.mvc.view.prefix=/WEB-INF/ spring.mvc.view.prefix=/WEB-INF/view/ spring.mvc.view.prefix=/resource/WEB-INF/view/ spring.mvc.view.prefix=F:/Projects/spring-mvc-demo/src/main/resources/WEB-INF/view/

它们中的每一个都返回相同的资源未找到堆栈跟踪。

2021-06-28 20:25:08.403 DEBUG 28116 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/", parameters=
2021-06-28 20:25:08.406 DEBUG 28116 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.springdemo.mvc.HomeController#showPage()
2021-06-28 20:25:08.420 DEBUG 28116 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8]
2021-06-28 20:25:08.420 DEBUG 28116 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView  : View name 'main-menu', model 
2021-06-28 20:25:08.421 DEBUG 28116 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView  : Forwarding to [/WEB-INF/view/main-menu.jsp]
2021-06-28 20:25:08.424 DEBUG 28116 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "FORWARD" dispatch for GET "/WEB-INF/view/main-menu.jsp", parameters=
2021-06-28 20:25:08.426 DEBUG 28116 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/], Classpath [resources/], Classpath [static/], Classpath [public/], ServletContext [/]]
2021-06-28 20:25:08.426  WARN 28116 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler     : Path with "WEB-INF" or "META-INF": [WEB-INF/view/main-menu.jsp]
2021-06-28 20:25:08.426 DEBUG 28116 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found
2021-06-28 20:25:08.426 DEBUG 28116 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "FORWARD" dispatch, status 404
2021-06-28 20:25:08.427 DEBUG 28116 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
2021-06-28 20:25:08.428 DEBUG 28116 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters=
2021-06-28 20:25:08.428 DEBUG 28116 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2021-06-28 20:25:08.442 DEBUG 28116 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2021-06-28 20:25:08.445 DEBUG 28116 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 404

【问题讨论】:

您期望的行为究竟是什么?你有read the documentation@RestController 吗? 我不确定你在这里问什么。我期待加载一个页面,该页面在页面正文中包含我的 main-menu.jsp 文件。我链接到一个页面,我在该页面上阅读了 2 个注释的差异。就像我在帖子中所说的那样,@Controller@RestController 之间的唯一区别是 @RestController 捆绑了 @Controller@ResponseBody。讲师的代码不使用@ResponseBody,但使用@Controller 运行良好。为什么我的工作方式和他的不一样? 从您的错误消息中可以看出您正在使用 Spring Boot,这是构建 Spring 应用程序的现代方式,但 bean XML sn-p 表明您正在尝试混合配置策略(具体来说,配置为在外部容器中使用,而不是使用现代的“只需运行main”方法)。您需要提供有关如何启动应用程序的更多信息。 我已将我的文件添加到原始问题中。我肯定在使用 main 方法来启动我的应用程序,它是由 IntelliJ 自动生成的。我确实注意到讲师没有主要方法。在 Eclipse 中,他简单地右键单击包并选择运行为 >>> 在服务器上运行。从您的评论看来,我必须调整他给我的 xml 文件以允许我从 main 方法运行? 您的讲师似乎使用了过时的设置(即“在服务器上运行”位)。您是否需要严格按照课程进行? 【参考方案1】:

你要做的是检查@Controller@RestController之间的简单区别

当您使用简单的@Controller 时,它只是创建一个地图模型并返回一个视图,但我们需要在我们的 Rest APIS 中实时响应 json,因此您需要使用@RestController,因为

@RestController = @Controller+@ResponseBody 但是当您使用@Controller 时,如果您想直接在JSON 中写入数据,则必须使用@ResponseBody

谢谢

这是参考

https://www.javacodegeeks.com/2017/08/difference-restcontroller-controller-annotation-spring-mvc-rest.html#:~:text=The%20%40Controller%20is%20a%20common,of%20%40Controller%20%2B%20%40ResponseBody%20.

【讨论】:

【参考方案2】:

几天前我遇到了类似的问题。看来您正在尝试使用 Spring Boot。请尝试删除 web.xml 并按照以下代码 sn-ps 进行某些更改。这对我有用。

DemoApplication.java

    @SpringBootApplication
public class DemoApplication  extends SpringBootServletInitializer 
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) 
        return builder.sources(DemoApplication.class);
    
    public static void main(String[] args) 
        SpringApplication.run(DemoApplication.class, args);
    


application.properties

spring.mvc.view.prefix= /WEB-INF/

spring.mvc.view.suffix= .jsp

Project Structure for adding jsp files

Home Controller.java

@Controller
@Slf4j
public class HomeController 
    @RequestMapping(value = "/home", method = RequestMethod.GET)
    public String home(Locale locale, Model model) 
        log.info("Welcome home! The client locale is .", locale);

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );

        return "home1";
    

PS:这是使用@Controller 运行的配置。

【讨论】:

嗨 Asmin,您的建议非常适合我的构建,但现在它似乎无法识别我的视图所在的文件夹。您有什么建议可以帮助我获得它跑步?我已经用第 5 次编辑更新了我的帖子,其中包含我到目前为止所做的事情和我的堆栈跟踪。感谢您的帮助。 再想一想,我相信我需要提出一个新问题。您的解决方案适用于我最初的问题,即如何让 @Controller 在我的代码中工作。新问题现在显示找不到资源。谢谢您的帮助。我会继续并将您的答案标记为解决方案。 @skidwiz 请尝试我的答案所附的项目结构,并将您的观点从资源之外带入新文件夹 webapp。让我知道它是否有效。

以上是关于为啥我的 Spring 应用程序使用 @RestController 而不是 @Controller的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Spring 应用程序使用 @RestController 而不是 @Controller

RESTful 接口调试分享利器 restc

为啥我的 Spring 应用程序无法识别有人已经登录?

为啥在将 Spring Data JPA 与 Spring Boot 结合使用时,我的数据库自定义没有得到应用?

为啥 Spring 忽略了我的 @DependsOn 注释?

使用Docker发布应用