sss我们以debug方法对如下方法进行分析,通过客户端 http://localhost:8080/ 进行登录请求:
ssdsdsdsdsdsdsdsdsdsdsdsdssds
dsdsdssdsss
视图解析
sss视图的处理方式我们大致分为三种,如下图:
ssdsdsdsdssdsdsdsdsdsddsadsad
sss接下来我们以重定向为例,大致分析一下视图解析原理流程。
浅析视图解析原理流程
sss在前几篇文章,我们分析了处理参数,解析参数,对数据进行响应,也就是生成相应的ModelAndView的相关源码,他们分别对应下图中的方法,而对于ModelAndView中的View的处理,就是我们对视图的解析。
sss在解析完参数,执行完方法体,并且对数据进行响应后,也就是生成了相应的ModelAndView(其实里面就存储了视图view),而视图和数据都会被放在ModelAndViewContainer 里面,通过下图和上图我们可知:
sdssds
sss[总结 1]:方法的参数是一个自定义类型 (User)对象(从请求参数中确定的),把他放在 ModelAndViewContainer。
sss[总结 2]:任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址),如果返回的为空,则读取默认的视图名(其实就是跳转回请求的页面)。
sss[注]:返回ModelAndView后,在处理派发结果之前(也就是页面如何响应),还有拦截器的相关操作,不过我们下篇文章再说。
处理派发结果的方法:ss= this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
sss[注]:render()方法是对页面进行渲染,我们可以看一下View,是一个接口,并且只有两个方法:
解析 render(mv, request, response) 方法:
①、我们如何根据方法的视图名(viewName)得到 View 对象【定义页面的渲染逻辑】呢?
sss我们遍历所有的视图解析器(5个),看能否根据当前返回值(viewName)得到View对象,如果能就返回,否则就遍历下一个视图解析器:
sdsss①、首先是ContentNegotiatingViewResolver这个视图解析器,该解析器包含了其他四个解析器(所以说其实我们遍历不到剩下的四个视图解析器),其逻辑如下(下图的三个方法):
sddssss⒈、首先是通过内容协商管理器的协商原理,找出请求发过来的所有能接收的媒体类型List< MediaType > requestedMediaTypes。
sddssss⒉、然后遍历其余的迭代器(因为ContentNegotiatingViewResolver这个视图解析器包含了其余的解析器),找出能解析视图名(viewName)的视图view,最终添加到List< View > candidateViews中。
sss[注]:因为我们是以返回值即视图名viewName是重定向为例的,所以到此,我们得到的视图解析器是ThymeleafViewResolver,它首先判断是否是以"redirect"开头,然后利用subString()得到"/main.html", 最后new一个 RedirectView(),将"/main.html"放到其中。
sss[注]:视图解析器其实就有一个作用:就是得到view()对象。而内容协商管理器得到view()后就会利用requestedMediaTypes对其进行内容匹配。
sddssss3、最后遍历candidateViews,返回其中是重定向的view。否则,再让requestedMediaTypes和candidateViews进行匹配,返回一个view。类似于重走第二步,但是返回的是一个View而不是List< view>
sss[注]:最终得到了 redirect:/main.html 。
②、找到相应的视图view后,对其进行渲染:( 视图对象调用自定义的render进行页面渲染工作)
sdsdsss首先是将model合并,然后设置响应头,获得targetUrl,最后对其进行处理后通过response转发(response.sendRedirect(encodedURL);
)。
sss[注]:如果有一些属性需要重定向,则会把这些属性以查询参数的方式拼接到URL后边。比如 “/main.html?target=xxx”。
视图解析的不同方式:
sss返回值以 forward: 开始: new InternalResourceView(forwardUrl); --> 对其渲染的核心逻辑是:
ssdsdssdsdsddssrequest.getRequestDispatcher(path).forward(request, response)
sss返回值以 redirect: 开始: new RedirectView() --》 render就是重定向
sss返回值是普通字符串: new ThymeleafView()—> 然后进行渲染(调用模板引擎的process方法进行页面渲染(用writer输出))
sss由此,我们可以自定义视图解析器+自定义视图,然后对其进行渲染(render())。