一、问题描述
苍穹外卖在菜品分页查询功能实现的过程中,出现了找不到视图的情况
2024-07-12 21:54:20.860 ERROR 22488 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Could not resolve view with name 'admin/dish/page' in servlet with name 'dispatcherServlet'] with root causejavax.servlet.ServletException: Could not resolve view with name 'admin/dish/page' in servlet with name 'dispatcherServlet'at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1383) ~[spring-webmvc-5.3.22.jar:5.3.22]at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1148) ~[spring-webmvc-5.3.22.jar:5.3.22]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1087) ~[spring-webmvc-5.3.22.jar:5.3.22]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.22.jar:5.3.22]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.22.jar:5.3.22]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.22.jar:5.3.22]at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.65.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.22.jar:5.3.22]at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.65.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.65.jar:9.0.65]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.22.jar:5.3.22]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.65.jar:9.0.65]at java.base/java.lang.Thread.run(Thread.java:1623) ~[na:na]
原来的代码
@Controller
@RequestMapping("/admin/dish")
@Api(tags="菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 分页查询菜品*/@GetMapping("/page")@ApiOperation("菜品分页查询")public Result<PageResult> page( DishPageQueryDTO dishPageQueryDTO){log.info("菜品分页查询:{}",dishPageQueryDTO);PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);return Result.success(pageResult);}
}
二、解决的措施
将注解@Controller 更换成 @RestController即可。控制器方法返回的请求体,但注解却需要直接解析的是视图,导致Spring MVC视图解析失败
具体原因我们得去思考以下这两个注解到底有什么的不同
@RestController
和 @Controller
是Spring框架中用于处理HTTP请求的注解,它们之间存在一些关键的区别,主要体现在它们对响应体的处理方式上。
@Controller
@Controller
注解用于标记在一个类上,表明这个类是一个Spring MVC Controller处理器。- 当处理器方法返回字符串时,它通常被解释为视图名(View Name),然后Spring MVC会尝试解析这个视图名并渲染相应的视图。当使用
@Controller
注解时,通常会结合JSP、Thymeleaf等模板引擎来渲染HTML页面。@Controller
注解的处理器方法可以直接返回视图名(String类型),也可以返回ModelAndView
对象,后者包含了视图名和模型数据。- 如果需要返回JSON或XML等非HTML内容,则需要在处理器方法中使用
@ResponseBody
注解,或者将方法返回类型设置为ResponseEntity
、HttpEntity
等,来指定响应体。
@RestController
@RestController
是@Controller
和@ResponseBody
的组合注解。该类下的所有方法默认都会应用@ResponseBody
注解。- 使用
@RestController
注解的控制器类,其方法默认返回的数据会直接写入HTTP响应体(Response Body)中,通常用于构建restful Web服务。- 常见的返回类型包括
ResponseEntity
、HttpEntity
、String
(直接作为JSON或XML字符串返回)、以及任何可以被自动转换为JSON或XML的对象(Spring MVC通过消息转换器自动完成转换)。- 当你需要构建restful API时,
@RestController
是一个更合适的选择,因为它简化了代码,避免了在每个方法上都添加@ResponseBody
注解。
使用
@Controller
时,通常用于返回视图名以渲染页面,适用于传统的Web应用。使用
@RestController
时,通常用于构建restful API,返回的数据会直接作为响应体返回给客户端,适合前后端分离的应用场景。
三、猜测
所以我就在猜测,难道 菜品分页查询 这个功能需要用到 @ResponseBody这个注解么?不然为什么将
@Controller 更换成 @RestController问题就迎刃而解了?于是我尝试修改代码如下:
果然解决了
所以@ResponseBody到底有什么用呢,再来探讨一下
@ResponseBody
是Spring MVC中用于将控制器方法的返回值绑定到HTTP响应体上