今日分享开始啦,请大家多多指教~
在 Spring Boot 项目中,有的时候我们想返回一段 JSON,结果却忘了写 @ResponseBody 注解,像下面这样:
@Controller
public class HelloController {
@GetMapping("/01")
public void hello() {
System.out.println("01");
}
}
这个时候当项目跑起来,肯定会报错,具体报什么错,则要看用的什么视图解析器,如果用了 Freemarker,你可能会看到如下错误:
这个错误是说陷入到循环调用中了。
如果用了 Thymeleaf,你可能会看到如下错误:
这个是说一个名叫 01 的视图不存在。
我只是少加了一个 @ResponseBody 注解而已,为什么用不同的视图解析器会报不同的错误?并且这些错误实在看不出和 @ResponseBody 注解有什么关联。
1.方法入口
- SpringMVC 源码分析之 DispatcherServlet
在这篇文章中,有一个小小细节,就是在 doDispatch 方法中,有如下一段代码:
applyDefaultViewName(processedRequest, mv);
当这段代码执行的时候,接口方法已经通过反射调用完成了,并且将返回值封装成了一个 ModelAndView 对象(如果接口方法用到了 @ResponseBody 注解,则此时拿到的 ModelAndView 对象为 null),但是这个时候的 ModelAndView 对象还没有渲染,此时会调用 applyDefaultViewName 方法去判断返回的 ModelAndView 对象中有没有 view,如果没有,则给出一个默认的视图名。
这行代码就是切入点,接下来我们就来分析一下 applyDefaultViewName 方法。
2.applyDefaultViewName
private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception {
if (mv != null && !mv.hasView()) {
String defaultViewName = getDefaultViewName(request);
if (defaultViewName != null) {
mv.setViewName(defaultViewName);
}
}
}
可以