Spring MVC学习—ViewSolvsolver视图解析器的详细介绍与使用案例

Posted L-Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring MVC学习—ViewSolvsolver视图解析器的详细介绍与使用案例相关的知识,希望对你有一定的参考价值。

  基于最新Spring 5.x,详细介绍了Spring MVC的ViewSolvsolver视图解析器组件,并提供了详细的使用案例。

  此前我们学习了Spring MVC中的核心组件以及请求的执行流程,现在让我们专门来学习ViewSolvsolver 视图解析器组件的功能和使用。

Spring MVC学习 系列文章

Spring MVC学习(1)—MVC的介绍以及Spring MVC的入门案例

Spring MVC学习(2)—Spring MVC中容器的层次结构以及父子容器的概念

Spring MVC学习(3)—Spring MVC中的核心组件以及请求的执行流程

Spring MVC学习(4)—ViewSolvsolver视图解析器的详细介绍与使用案例

Spring MVC学习(5)—基于注解的Controller控制器的配置全解【一万字】

Spring MVC学习(6)—Spring数据类型转换机制全解【一万字】

Spring MVC学习(7)—Validation基于注解的声明式数据校验机制全解【一万字】

Spring MVC学习(8)—HandlerInterceptor处理器拦截器机制全解

Spring MVC学习(9)—项目统一异常处理机制详解与使用案例

Spring MVC学习(10)—文件上传配置、DispatcherServlet的路径配置、请求和响应内容编码

Spring MVC学习(11)—跨域的介绍以及使用CORS解决跨域问题

1 ViewSolvsolver 的概述

  Spring MVC 定义了 ViewSolvsolver 和 View 接口,这些接口允许我们在Web应用中通过模型数据对视图模版进行渲染并返回给浏览器,而无需依赖特定的视图技术。
  ViewResolver 提供逻辑视图名称到实际物理视图的映射,即将逻辑视图名解析为View视图对象,其中包含了真实物理视图的信息(比如url路径、locale国际化信息)。View 则用于在将模型数据移交给特定视图技术之前进行数据准备,随后调用对应的视图技术进行视图渲染。
  ViewResolver的不同实现具有不同的逻辑视图名到物理视图的映射算法,常见实现的uml类图结构如下:
在这里插入图片描述

1.1 AbstractCachingViewResolver

  实现了ViewResolver接口的便捷抽象基类。继承了AbstractCachingViewResolver的子类将默认缓存它们已经解析了的View视图实例,这意味着无论初始View视图的检索成本有多高,视图解析都不会是性能问题,即缓存可以提高某些视图技术的性能。
  我们可以通过将cache属性设置为false来关闭缓存。此外,如果必须在运行时刷新某个视图(例如,当修改FreeMarker模板时),则可以使用removeFromCache(String viewName,Locale loc)方法。
  默认最大缓存1024个,缓存的View的key为viewName和locale的组合:
在这里插入图片描述

2 XmlViewResolver

  ViewResolver的一种实现,继承了AbstractCachingViewResolver,具有缓存View视图的能力。
  XmlViewResolver支持接受XML配置文件,配置文件中存放的是自己配置的View bean,每一个View bean都有自己的id/name,XmlViewResolver将根据Controller处理器方法返回的逻辑视图名称到指定的XML配置文件中寻找对应名称的 View bean并返回,用于处理视图,这就是它的工作(将逻辑视图名解析为真正的View视图对象)原理!
  默认配置文件是/WEB-INF/views.xml,如果不使用默认配置,那么可以在XmlViewResolver的location属性中指定它的位置。
  XmlViewResolver指定的cachekey就是viewName:
在这里插入图片描述

2.1 使用案例

  如下案例,一个Controller:

/**
 * @author lx
 */
@Controller
public class XmlViewResolverController {

    @RequestMapping("/xmlViewResolver")
    public ModelAndView handle() {
        ModelAndView modelAndView = new ModelAndView();
        //添加模型数据
        modelAndView.addObject("msg", "xmlViewResolver测试");
        //添加逻辑视图名
        modelAndView.setViewName("xvr");
        return modelAndView;
    }
}

  spring-mvc-config.xml配置文件,我们手动注册了一个XmlViewResolver,并指定配置文件位置为类路径下面(resources下面)的views.xml文件!

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--扫描包-->
    <context:component-scan base-package="com.spring.mvc"/>

    <!--手动配置一个XmlViewResolver-->
    <bean class="org.springframework.web.servlet.view.XmlViewResolver">
        <!--指定配置文件位置-->
        <property name="location" value="classpath:views.xml"/>
    </bean>
    
</beans>

  views.xml,我们在其中配置一个View bean,bean的id为xvr,与Controller方法中设置的逻辑视图名一致!

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--配置一个InternalResourceView类型的View bean,name或者id属性需要与逻辑视图名匹配-->
    <bean id="xvr" class="org.springframework.web.servlet.view.InternalResourceView">
        <!--配置jsp或者其他资源的url路径,请求将对转发到指定的资源-->
        <property name="url" value="/WEB-INF/jsp/xvr.jsp"/>
    </bean>
</beans>

  /WEB-INF/jsp目录下配置一个jsp视图模版xvr.jsp:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>XmlViewResolver</title>
</head>
<body>
<h1>XmlViewResolver!</h1>
<br/>
<span style="color: #dc143c; ">${msg}</span>
<br/>
</body>
</html>

  项目总体结构如下:
在这里插入图片描述
  启动项目,访问/xmlViewResolver,结果如下:
在这里插入图片描述
  说明我们配置成功!

3 ResourceBundleViewResolver

  ViewResolver的一种实现,继承了AbstractCachingViewResolver,具有缓存View视图的能力。
  ResourceBundleViewResolver支持接受properties配置文件,配置文件的编写和XmlViewResolver的XML配置文件的编写有很大区别。properties中key的编写就是通过viewname.(class)指定View视图的实现类,ket的前缀就是逻辑视图名,通过viewname.propertyName指定某个View视图的属性。
  ResourceBundleViewResolver将根据Controller处理器方法返回的逻辑视图名称到指定的properties配置文件中寻找对应名称的 View bean并返回,用于处理视图,这就是它的工作(将逻辑视图名解析为真正的View视图对象)原理!
  默认配置文件是classpath下面的views.properties,如果不使用默认配置,那么可以在ResourceBundleViewResolver的basename或者basenames属性中指定,这里只能指定配置文件前缀,,如指定的baseName是base,那么base.properties、baseabc.properties等等以base开始的属性文件都会被Spring当做ResourceBundleViewResolver解析视图的资源文件。
  默认最大缓存1024个,缓存的View的key为viewName和locale的组合:
在这里插入图片描述

3.1 使用案例

  如下案例,一个Controller:

/**
 * @author lx
 */
@Controller
public class ResourceBundleViewResolverController {

    @RequestMapping("/resourceBundleViewResolver")
    public ModelAndView handle() {
        ModelAndView modelAndView = new ModelAndView();
        //添加模型数据
        modelAndView.addObject("msg", "ResourceBundleViewResolver测试");
        //添加逻辑视图名
        modelAndView.setViewName("rbvr");
        return modelAndView;
    }
}

  spring-mvc-config.xml配置文件中我们手动注册了一个ResourceBundleViewResolver,basename前缀为view。

<!--手动配置一个ResourceBundleViewResolver-->
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    <!--指定配置文件前缀-->
    <property name="basename" value="view"/>
</bean>

  在resources目录下添加一个views.properties,我们在其中配置一个View, id为rbvr,与Controller方法中设置的逻辑视图名一致!

#指定视图名rbvr以及通过(class)指定View所属类型
rbvr.(class)=org.springframework.web.servlet.view.InternalResourceView
#指定某个视图名的类型的属性,这里指定rbvr视图的url属性
rbvr.url=/WEB-INF/jsp/rbvr.jsp

  在/WEB-INF/jsp目录下配置一个jsp视图模版rbvr.jsp:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>ResourceBundleViewResolver</title>
</head>
<body>
<h1>ResourceBundleViewResolver!</h1>
<br/>
<span style="color: #dc143c; ">${msg}</span>
<br/>
</body>
</html>

  启动项目,访问/xmlViewResolver,结果如下:
在这里插入图片描述
  说明我们配置成功!

4 UrlBasedViewResolver

  ViewSolver的简单实现,继承了AbstractCachingViewResolver,具有缓存View视图的能力。
  UrlBasedViewResolver,提供了一种通过拼接前后缀的方式来方便的获取逻辑视图对应的真实物理视图URL的功能。我们可以通过配置prefix属性指定一个URL前缀,通过suffix属性指定一个URL后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的物理视图URL了。比如prefix设置为“/WEB-INF/pages/”,suffix设置为“.jsp”,返回的逻辑视图为“index”,那么最终的物理视图URL就是“/WEB-INF/pages/index.jsp”默认情况下。prefix和suffix都是空字符串,设置为null同样被解析为空串!
  配置UrlBasedViewResolver时,必须指定一个viewClass属性,该UrlBasedViewResolver会将所有的逻辑视图名解析为该类型的View对象。由于从逻辑视图到物理视图(路径)的映射就是拼接URL的规则,并且解析出来的viewClass指定为一种,因此我们必须要像XmlViewResolver和ResourceBundleViewResolver那样手动配置View的映射以及实现,而是由UrlBasedViewResolver自动创建!
  UrlBasedViewResolver将尝试检查逻辑视图对应的物理资源是否确实存在。但是,如果viewClass为InternalResourceView,则通常无法确定目标资源是否真实存在。在这种情况下,UrlBasedViewResolver将始终返回一个任何给定逻辑视图名称的InternalResourceView视图对象,无论它是否真实存在,永远不会返回null。因此,应将它配置为解析器链中的最后一个视图解析器(如果存在多个解析器),以尽量防止后续因物理视图资源找不到而返回的404响应!
  同时,可以为UrlBasedViewResolver设置viewNames属性,这是一个String数组,表示该UrlBasedViewResolver能解析的逻辑视图名,支持通配符匹配,比如*,如果没有设置viewNames(将会是null),或者设置了但是没有匹配,那么resolveViewName将会返回null,进而由下一个ViewResolver解析。
  XmlViewResolver指定的cachekey就是viewName:
在这里插入图片描述

4.1 使用案例

  如下案例,一个Controller:

/**
 * @author lx
 */
@Controller
public class UrlBasedViewResolverController {

    @RequestMapping("/urlBasedViewResolver")
    public ModelAndView handle() {
        ModelAndView modelAndView = new ModelAndView();
        //添加模型数据
        modelAndView.addObject("msg", "UrlBasedViewResolver测试");
        //添加逻辑视图名
        modelAndView.setViewName("ubvr");
        return modelAndView;
    }
}

  在spring-mvc-config.xml配置文件中我们手动注册一个UrlBasedViewResolver。

<!--手动配置一个UrlBasedViewResolver-->
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <!--指定物理视图路径前缀-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--指定物理视图路径后缀-->
    <property name="suffix" value=".jsp"/>
    <!--必须指定解析的View视图的类型-->
    <!--这里指定为InternalResourceView,那么将会将请求转发到物理视图的路径-->
    <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
</bean>

  在/WEB-INF/jsp目录下配置一个jsp视图模版ubvr.jsp:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>UrlBasedViewResolver</title>
</head>
<body>
<h1>UrlBasedViewResolver!</h1>
<br/>
<span style="color: #dc143c; ">${msg}</span>
<br/>
</body>
</html>

  启动项目,访问/ urlBasedViewResolver,结果如下:
在这里插入图片描述
  说明我们配置成功,并且它的配置更加简单!

5 InternalResourceViewResolver

  专门用于支持内部资源视图InternalResourceView(实际上,就是为了支持Servlet和JSP资源)及其子类(如 JstlView 和TilesView)的 UrlBasedViewResolver 的便捷子类。
  相比于父类UrlBasedViewResolver,不需要指定viewClass属性,默认的解析得到的视图类型就是InternalResourceView,InternalResourceView的一个特性就是它的会把Controller处理器方法返回的model模型属性都存放到对应的request中,然后通过RequestDispatcher在服务器端把请求forword转发到目标物理资源视图URL。基于InternalResourceView的隐匿的转发机制,对于访问/WEB-INF/下面的受保护的资源来说是一种非常方便快捷且安全的方式了。
  UrlBasedViewResolver通过设置viewClass为InternalResourceView的类型,也可以达到同样的效果!同样的,如果存在解析器链,InternalResourceViewResolver始终需要放在最后一个,因为它将尝试解析任何给定的逻辑视图名称并返回一个对应的InternalResourceView,无论对应的资源是否确实存在。.。

5.1 使用案例

  如下案例,一个Controller:

/**
 * @author lx
 */
@Controller
public class InternalResourceViewResolverController {

    @RequestMapping("/internalResourceViewResolver")
    public ModelAndView handle() {
        ModelAndView modelAndView = new ModelAndView();
        //添加模型数据
        modelAndView.addObject("msg", "InternalResourceViewResolver测试");
        //添加逻辑视图名
        modelAndView.setViewName("irvr");
        return modelAndView;
    }
}

  在spring-mvc-config.xml配置文件中我们手动注册一个InternalResourceViewResolver,注意此时我们应该将此前配置的UrlBasedViewResolver注释掉!

<!--手动配置一个InternalResourceViewResolver-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--指定物理视图路径前缀-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--指定物理视图路径后缀-->
    <property name="suffix" value=".jsp"/>
</bean>

  在/WEB-INF/jsp目录下配置一个jsp视图模版irvr.jsp:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <title>InternalResourceViewResolver</title>
</head>
<body>
<h1>InternalResourceViewResolver!</h1>
<br/>
<span style="color: #dc143c; ">${msg}</span>
<br/>
</body>
</html>

  启动项目,访问/internalResourceViewResolver,结果如下:
在这里插入图片描述
  说明我们配置成功!

6 FreeMarkerViewResolver

  专门用于支持FreeMarkerView的 UrlBasedViewResolver 的便捷子类,和InternalResourceViewResolver比较类似,FreeMarkerViewResolver默认会将逻辑视图名解析为FreeMarkerView视图。
  FreeMarkerViewResolver将检查指定模板资源是否存在,并且仅在实际找到模板时返回非null的 View 对象。
  虽然View仅仅是进行了数据的准备和API的调用,但是由于JSP视图的渲染和数据填充是Servlet容器和tomcat服务器天然支持和实现的,因此不必引入专门的依赖,而对于FreeMarker模版的渲染和数据填充技术则需要引入专门的FreeMarker依赖,这样FreeMarkerView才能正常工作!

<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
  <version>2.3.30</version>
</dependency>
<!--用于引入FreeMarkerConfigurationFactory-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>5.2.8.RELEASE</version>
</dependency>

6.1 使用案例

  如下案例,一个Controller:

/**
 * @author lx
 */
@Controller
public class FreeMarkerViewResolverController {

    @RequestMapping("/freeMarkerViewResolver")
    public ModelAndView handle() {
        ModelAndView modelAndView = new ModelAndView();
        //添加模型数据
        modelAndView.addObject("msg", "FreeMarkerViewResolver测试");
        //添加逻辑视图名
        modelAndView.setViewName("fmvr");
        return modelAndView;
    }
}

  在spring-mvc-config.xml配置文件中我们手动注册一个FreeMarkerViewResolver,并且指定配置信息:

<!-- 手动配置一个FreeMarkerViewResolver,专门用于解析FreeMarker视图 -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="suffix" value=".ftl"/>
    <property name="contentType" value="text/html;charset=UTF-8" />
</bean>

<!--freemarkerConfig-->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <!-- 配置freeMarker的模板路径 -->
    <property name="templateLoaderPath" value="/WEB-INF/ftl"/>
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

  在/WEB-INF/ftl目录下配置一个freeMarker视图模版fmvr.ftl:

<!DOCTYPE html>
<html lang="zn_CH">
<head>
    <title>FreeMarkerViewResolver</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>FreeMarkerViewResolver!</h1>
<br/>
<span style="color: #dc143c; ">${msg}</span>
<br/>
</body>以上是关于Spring MVC学习—ViewSolvsolver视图解析器的详细介绍与使用案例的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC学习笔记---Spring MVC 的HelloWorld

Spring MVC学习笔记---Spring MVC 的HelloWorld

Spring MVC学习—Spring MVC中容器的层次结构以及父子容器的概念

Spring MVC学习笔记——Controller

Spring MVC学习笔记——AbstractController

Spring MVC学习笔记——WebContentGenerator