SpringMVC之源码分析--ViewResolver(三)

概述

本节学习下ViewResolverComposite的功能,简单来说,该类的作用就是把多个ViewResolver视图解析器进行组装,内部使用list存储配置使用的视图解析器。

本系列文章是基于Spring5.0.5RELEASE。

源码

ViewResolverComposite实现ViewResolver接口,源码如下;

public class ViewResolverComposite implements ViewResolver, Ordered, InitializingBean,
    ApplicationContextAware, ServletContextAware {
    // 用于存储使用的ViewResolver容器
    private final List<ViewResolver> viewResolvers = new ArrayList<>();
    // 支持排序
    // 此排序并不影响上面list中的顺序
    private int order = Ordered.LOWEST_PRECEDENCE;

    ... ...

    /**
     *根据逻辑视图名称进行解析
     */
    @Override
    @Nullable
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        // 迭代配置使用的ViewResolver集合
        for (ViewResolver viewResolver : this.viewResolvers) {
            // 逐一调用不同的解析器进行解析
            View view = viewResolver.resolveViewName(viewName, locale);
            // 找到View即返回
            if (view != null) {
                return view;
            }
        }
        // 未找到返回null
        return null;
    }

    ... ...
}

以上是ViewResolverComposite核心代码。

实战

练习ViewResolverComposite的使用。

  • 项目结构

SpringMVC之源码分析--ViewResolver(三)

  • pom文件

通过maven构建,引入依赖的jar坐标,代码如下:

<!-- Spring MVC依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>
<!-- Servlet依赖 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<!-- JSP依赖的JSTL -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
  • Spring配置文件

通过此文件配置Spring MVC的组件,代码如下:

<!-- 扫描指定路径 -->
<context:component-scan base-package="com.github.dalianghe.controller"/>

<!-- 配置ViewResolverComposite视图解析器,并装载两个视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.ViewResolverComposite">
    <property name="viewResolvers">
        <list>
            <ref bean="internalResourceViewResolver"/>
            <ref bean="beanNameViewResolver"/>
        </list>
    </property>
    <property name="order" value="1"/>
</bean>

<!-- 本例辅助视图解析器1 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="3"/>
</bean>

<!-- 本例辅助视图解析器2 -->
<bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <property name="order" value="2"/>
</bean>

<bean id="test" class="org.springframework.web.servlet.view.JstlView">
    <property name="url" value="/WEB-INF/jsp/test.jsp"/>
</bean>
  • 部署描述文件

配置Spring MVC核心控制器DispatcherSerlvet,代码如下:

<servlet>
    <!-- Servlet名称,可任意定义,但必须与servlet-mapping中对应 -->
    <servlet-name>dispatcher</servlet-name>
    <!-- 指定Spring MVC核心控制类,即J2EE规范中的前端控制器(Front Controller) -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定Spring MVC配置文件,默认在WEB-INF目录下,切名字为[servlet-name]-servlet.xml,此文件中配置web相关内容,比如:指定扫描Controller路径、配置逻辑视图前缀后缀、上传文件等等 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-servlet.xml</param-value>
    </init-param>
    <!-- 此配置的值为正整数时,表示容器启动时初始化,即调用Servlet的init方法 -->
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>
<!-- 定义servlet映射 -->
<servlet-mapping>
    <!-- 与servlet中servlet-name对应 -->
    <servlet-name>dispatcher</servlet-name>
    <!-- 映射所有的url -->
    <url-pattern>/</url-pattern>
</servlet-mapping>
  • 处理器

编写处理器,本例使用注解,代码如下:

@Controller
public class DemoController {
    @GetMapping("/viewResolverComposite")
    public String viewResolverComposite(){
        return "test";
    }
}
  • 测试

测试一:视图解析器属性order并不影响ViewResolverComposite组装使用的视图解析器顺序

根据以上配置,如果order影响的话,视图解析应有BeanNameViewResolver进行解析,但通过测试结果并不是由其进行的处理,故order不影响内部组装顺序,如下图:

SpringMVC之源码分析--ViewResolver(三)

测试二:ViewResolverComposite组装的视图解析器顺序由其存入顺序影响,即如上配置属性viewResolvers的list从上往下一次处理。

把viewResolvers的list数据顺序调整一下,调整后如下:

<property name="viewResolvers">
    <list>
        <ref bean="beanNameViewResolver"/>
        <ref bean="internalResourceViewResolver"/>
    </list>
</property>

重启再次断点查看,如下图:

SpringMVC之源码分析--ViewResolver(三)

此时处理视图解析的变更为BeanNameViewResolver。

测试三:测试order功能

我们设置Spring中的ViewResolver的order属性,如下:

<!-- 配置ViewResolverComposite视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.ViewResolverComposite">
    <property name="viewResolvers">
        <list>
            <ref bean="beanNameViewResolver"/>
            <ref bean="internalResourceViewResolver"/>

        </list>
    </property>
    <property name="order" value="1"/>
</bean>

<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="3"/>
</bean>

<bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <property name="order" value="2"/>
</bean>

验证Spring加载的视图解析器是否与我们的顺序一致,启动时如果如下图:

SpringMVC之源码分析--ViewResolver(三)

用户请求时,结果如下图:

SpringMVC之源码分析--ViewResolver(三)

由结果可知,Spring是按我们配置的order属性进行排序的。

总结

本章介绍了ViewResolverComposite类,根据测试,了解到order属性不影响ViewResolverComposite中配置使用的视图解析器顺序。order控制Spring加载使用视图解析器的顺序。

最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!

SpringMVC之源码分析--ViewResolver(三)

相关推荐