Springboot配置多个视图解析器,关于ViewResolver内容协商原理

近期看了点Spring boot的框架源码,研究了一下WEB Mvc的视图解析器,记录一下,以备以后查阅.如果认知错误,还请小伙伴指教讨论.

  1. 几个核心的类
    DispatherServlet(前端控制器)、ViewResolver(视图解析器)、View(视图类)

  2. 以下使用两个视图解析器作为例子,比较好区别
    其一:ThymeleafViewResolver
    另一:InternalResourceViewResolver(系统默认实现)
    在WebMvcAutoConfiguration 自动注入

Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第1张图片
1.DispatcherServlet在选择视图解析器的时候,以优先级为处理原则,此优先级是根据该ViewResolver实现Ordered接口或者使用@Order注解赋值,数字最小优先级越高为原则.
2.通过判断,返回一个具体的View类,最终通过3、4步骤渲染成HTML或者是XML等视图内容.

ViewResolver视图解析器在DispatcherServlet解析

源码类DispatcherServlet

  1. 关于ViewResovlers排序
    系统通过下图该方法,对于视图解析器进行排序sort,排序的原则还是按照Order的大小(ps viewResolvers是一个List集合)
    Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第2张图片
  2. 关于匹配View对象的方法,遍历viewResolvers,匹配到第一个View对象,则返回.

Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第3张图片

ViewResolver内容协商原理

代码入口:

多视图产生的常见错误(当我们配置多个视图解析器时,出现只支持一种视图解析器器,其他类型产生404)

在工作中,我们发现,如果我们新建了一个视图解析器,这里我使用ThymeleafViewResolver作为例子,我们会发现,如果该视图解析器只配置了支持HTML的解析,在我们访问JSP页面时候,会出现404的错误.

前面我们已经知道,视图解析器在解析的时候,是根据Order的大小来判断优先级.

上面这个错误,我们如果尝试以源码的角度来解析,这是因为我们这时候系统出现了两个视图解析器,而优先级ThymeleafViewResolver比InternalResourceViewResolver高,这里我们可以看一下源码:

  1. ThymeleafAutoConfiguration
    我们可以很清楚的看出来ThymeleafViewResolver的Order为 Ordered.LOWEST_PRECEDENCE - 5
    Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第4张图片
  2. InternalResourceViewResolver
    果然经过层层跳转,发现自动注入的InternalResourceViewResolver的优先级为最低级.注意:这里指的是自动注入,就是在我们不经过任何改造的情况下,是属于最低级.
    Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第5张图片
    下图是通过debug的方式,看到真实的排序是跟我们看到的源码是一致的.
    Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第6张图片

该错误的解决思路

1.可以通过自定义视图解析器,设置其优先级高于 ThymeleafAutoConfiguration :Ordered.LOWEST_PRECEDENCE - 5.
Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第7张图片
通过debug的方式,看到此时自定义的InternalResourceViewResolver已经是优先级最高.
Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第8张图片
2.其实到这里,还是不能处理兼容处理多种格式,例如同时兼容HTML和XML,这里还是同样用源码的角度来解释这个现象,首先我们需要注意的是ContentNegotiatingViewResolver这个视图解析器,其实这个视图解析器就是一个视图内容的协商,而且这个视图解析器如上图所示,它的优先级是最高的,这一点可以去看它的Order.
先说它的作用,它其实是去关联除了自己以外的所有视图解析器,可以通过它来实现一种资源返回多种形式.
两个比较重要的参数:

  • favorPathExtension:是否支持扩展名,默认为true(支持),扩展名指的xxx.json、xxx.xml等形式
  • favorParameter:是否启用参数支持,默认为true(支持),即xxx?format=json、xxx?format=xml等形式,这里的参数名默认为format,可以通过配置改变。

说完该视图解析器的简单介绍,说说为什么不能实现多种解析的兼容,如下图可以看到,默认的处理contentType都为text/html,所以当匹配到优先级为最先时,系统就会直接交给这个视图处理器处理,所以会出现支持不了的情况.
Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第9张图片
这里通过设置contenType来区别各个匹配器,这里我设置了以text/xml,然后去访问,可以达到不同的效果
Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第10张图片

实验结果

  • 实验一
  • 用text/html显示html页面.
    Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第11张图片
  • 用text/xml显示html页面.

Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第12张图片
实验二,
使用format参数,也可以显示不同的页面,使用不同的处理器
Springboot配置多个视图解析器,关于ViewResolver内容协商原理_第13张图片

你可能感兴趣的:(WebMVC,ViewResolver,视图解析器)