视图解析器与视图的底层原理
看完一遍尚硅谷的视频后自己琢磨,不懂就继续看视频,内容可能多有漏洞,如有不对,还望大佬们斧正
简单的控制器方法,实现页面的跳转以及添加错误信息。
@PostMapping("/login")
public String main(User user, HttpSession session, Model model) {
if(user.getUserName().length()>0&&(user.getPassword().equals("123456"))) {
//登陆成功重定向main页面
session.setAttribute("loginuser",user);
return "redirect:/main.html";
}else{
//输入错误信息,添加提示信息给msg并添加request域中
model.addAttribute("msg","账号或者密码错误");
return "login";
}
}
@GetMapping("/main.html")
public String mainPage(){
return "main";
}
同时在判断userName和password的if方法处和doDispatch打断点,进行debug调试
-
在提交登录请求之后,并不是直接使用doDispatch方法,在其之前有:run、service、invoke、process、doFilter、internalDoFilter、doPost、processRequest、doDispatch方法。
-
此时经历过一系列方法之后,此时的request域中已经获取到了当前请求
-
之后获取当前请求的处理器
-
之后获取处理器的适配器
-
然后从request中获取请求的方法,post请求,不进入以下if中的方法,而是在之后执行适配器的执行方法。
-
执行目标方法返回ModelAndView对象
-
handle方法的内容
-
再次进入handleInternal
-
可见,首先checkRequest判定我们是否支持request方法,而后判断此时的session是否为同步session,显示并不是,所以之后执行invokeHandlerMethod方法;
-
进入目标方法,先是数据绑定工厂,此处不深追
-
ServletInvocableHandlerMethod. 它是对 InvocableHandlerMethod 的扩
展,它增加了 返回值和响应状态码的处理 ,另外在
ServletInvocableHandlerMethod 有个内部类ConcurrentResultHandlerMethod 继承于它,支持 异常调用结果 处理, Servlet 容器下 Controller 在查找适配器时发起调用的最终就是 ServletInvocableHandlerMethod 。 -
ModelFactory是用来维护Model的,具体包含两个功能
(1)初始化Model
(2)处理器执行后将Model中相应的参数更新到SessionAttributes中 -
if中是参数处理器和返回值处理器
- 之后经过一系列的初始化操作将请求携带的信息给到相应的对象中
- 在数据成功匹配之后hanle方法执行。可见实际上是invokeAndHandle运作
- 之后returnValue是之前的model等等的所有数据
- 然后是返回值的解析
- 首先是返回值处理器的寻找,在14个处理器中通过for循环遍历,判断返回值类型是否与处理器所处理的一致
- 寻找handler,这个可以处理字符串参数
- 处理参数的具体方法:首先将returnValue转为字符串然后mavContainer存放,接着isRedirectViewName判断此时是否是需要重定向的页面
- isRedirectViewName判断路径前缀是否是redirect:
- 在方法执行完后,所有的参数此时都在mavContrainer中。同时,假如方法参数中有一个自定义类型的参数对象(从请求参数中确定的),就会把他重新放在ModelAndViewContrainler中
- 然后返回mav,将视图地址和数据放在ModelAndView对象中,此时handle方法执行完毕,mv=mav。
- 在接下来执行过程中会执行applyDefaultViewName,该方法是,在mv中没有视图的值,就给其一个默认的视图地址。
-
接下来是处理派发结果processDispatchResult(决定页面该如何响应)
-
render(mv, request, response);该方法执行视图的渲染
-
根据方法的String返回值得到view对象(相当于定义了页面的渲染逻辑)
- 所有的视图解析器尝试是否根据当前返回值得到view对象
- 根据返回值获取RedirectView
- resolveViewName该方法首先创建一个view,然后传参给新建立的view,再判断viewname的前缀;然后分别再进行处理
- 得到redirect:/main.html–>Thymeleaf new Redirect()
- ContentNegotiationViewResolver里面包含了下面的所有的视图解析器,其在内部还是利用所有视图解析器得到对象。RedirectView
- RedirectView如何渲染(重定向到一个页面):
1、获取目标url地址
2、response.sendRedirect(encodeURL);
至此,页面重定向就此解决,在处理过程中,如果方法还有其他注解也会一一的进行解析和处理