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

概述

上篇学习了Spring MVC ViewResolver视图解析器作用及处理流程,Spring为我们提供了丰富的视图解析器(见下图):SpringMVC之源码分析--ViewResolver(二)

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

BeanNameViewResolver

该视图解析器是根据处理器(handler)返回的逻辑视图名称,在应用上下文中查找该名称的视图bean对象(视图bean对象就是View的bean对象)。具有如下特点:

  • 视图bean对象需注册在Spring应用上下中,即由托管给Spring进行管理;
  • 处理器返回的逻辑视图名称为视图bean对象名称(或id);

源码

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

public class BeanNameViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered {
    // 实现Ordered接口,支持对个ViewResolver排序,值越小优先级越高
    private int order = Ordered.LOWEST_PRECEDENCE; 

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public int getOrder() {
        return this.order;
    }

    /**
     *实现ViewResolver接口方法
     *参数viewName就是处理器返回的逻辑视图名称
     */
    @Override
    @Nullable
    public View resolveViewName(String viewName, Locale locale) throws BeansException {
        // 获取上下文
        ApplicationContext context = obtainApplicationContext();
        // 查找上下文中是否有“viewName”的bean定义
        if (!context.containsBean(viewName)) {
            if (logger.isDebugEnabled()) {
                logger.debug("No matching bean found for view name '" + viewName + "'");
            }
            // Allow for ViewResolver chaining...
            return null;
        }
        // 判断“viewName”的bean对象是否是View类型
        if (!context.isTypeMatch(viewName, View.class)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Found matching bean for view name '" + viewName +
                        "' - to be ignored since it does not implement View");
            }
            // Since we're looking into the general ApplicationContext here,
            // let's accept this as a non-match and allow for chaining as well...
            return null;
        }
        // 返回上下文中指定名称(或id)的View类型的bean
        return context.getBean(viewName, View.class);
    }

}

实战

练习BeanNameViewResolver的使用。

  • 项目结构

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的组件,代码如下:

<!-- 使用默认的HandlerMapping和HandlerAdapter,指定扫描路径 -->
<context:component-scan base-package="com.github.dalianghe.controller"/>

<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <!-- 指定ViewResolver的顺序 -->
    <property name="order" value="1"/>
</bean>

<!-- 使用JstlView需引入jstl依赖 -->
<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 Demo1Controller {
    @RequestMapping(value = "/beanNameViewResolver")
    public String beanNameViewResolver(){
        return "test";
    }
}

以上例子,在Spring MVC容器中定义了BeanNameViewResolver视图解析器和id为test的InternalResourceView视图bean(可以替换),以上配置后,在handler处理器返回的逻辑视图名称为test的时候,就会使用id为test的视图bean对象(InternalResourceView)进行视图渲染。

总结

本章介绍了BeanNameViewResolver的源码及测试小例子,希望对大家有帮助。

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

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

相关推荐