springMVC4(13)视图解析器分类详解

《springMVC4(7)模型视图方法源码综合分析》一文中,我们介绍了ModelAndView的用法,它会在控制层方法调用完毕后作为返回值返回,里面封装好了我们的业务逻辑数据和视图对象或视图名

。下一步,视图对象往往会对模型进一步渲染,再由视图解析器进一步解析并向前端发出响应。在下面,我们详细介绍视图和视图解析器的各种分类。

在View接口中,定义了一个核心方法是:

void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

它的作用主要是渲染模型数据,整合web资源,并以特定形式响应给客户,这些形式可以是复杂JSP页面,也可以是简单的json、xml字符串。

针对不同的响应形式,spring为我们设计了不同的View实现类:

针对不同的视图对象,我们使用不同的视图解析器来完成实例化工作。我们可以在Spring上下文配置多个视图解析器,并通过order属性来指定他们之间的解析优先级顺序,order 越小,对应的 ViewResolver 将有越高的解析视图的权利。当一个 ViewResolver 在进行视图解析后返回的 View 对象是 null 的话就表示该 ViewResolver 不能解析该视图,这时候就交给优先级更低的进行解析,直到解析工作完成,如果所有视图解析器都不能完成将解析,则会抛出异常。

类似于视图,Spring也为我们提供了众多的视图解析器实现类:

1. AbstractCachingViewResolver

这是一个抽象类,这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找,如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的 map 中,接着再把新建的视图返回。使用这种视图缓存的方式可以把解析视图的性能问题降到最低。

2. UrlBasedViewResolver

继承了AbstractCachingViewResolver ,通过prefix、suffix**拼接 URL** 的方式来解析视图,支持返回的视图名称中包含 redirect: 、forward等前缀进行重定向或转发。使用 UrlBasedViewResolver 的时候必须指定属性 viewClass ,表示解析成哪种视图,一般使用较多的就是 InternalResourceView ,利用它来展现 jsp ,但是当我们使用 JSTL 的时候我们必须使用 JstlView 。下面是一段 UrlBasedViewResolver 的实例定义:

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
   <property name="prefix" value="/WEB-INF/" />
   <property name="suffix" value=".jsp" />
   <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
</bean>

3. InternalResourceViewResolver

它是 URLBasedViewResolver 的子类,所以 URLBasedViewResolver 支持的特性它都支持. InternalResourceViewResolver 会把返回的视图名称都解析为 InternalResourceView 对象, InternalResourceView 会把 Controller 处理器方法返回的模型属性都存放到对应的 request 属性中,然后通过 RequestDispatcher 在服务器端把请求 forword 重定向到目标 URL 。下面是一个配置实例:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/WEB-INF/"/>
       <property name="suffix" value=".jsp"></property>
    </bean>

如果我们需要使用JstlView,则需指定vlewClass属性为JstlView。

在前面的测试实例中,我们一直在使用这种视图解析器,所以不再举例。

4. BeanNameViewResolver

根据它的名字,我们将视图在spring容器中注册为Bean,Bean的id即为视图名。在我们控制层返回视图时,BeanNameViewResolver会自动根据我们的试图名找到对应的视图Bean进行解析,下面我们看一个实例:

1. 配置视图解析器和视图

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
   <property name="order" value="1"/><!-- 设置优先级最高,最先开始解析-->
</bean>

<bean id="hello" class="org.springframework.web.servlet.view.InternalResourceView">
   <property name="url" value="/WEB-INF/views/hello.jsp"/><!--访问对应的jsp文件-->
</bean>

2. 配置控制器

配置好视图和视图解析器后,我们可以在控制层通过如下方法访问视图:

@Controller
public class ViewController {
    @RequestMapping("view1")
    public String view1(){
        return "hello";//返回字符串直接为视图名称,解析器会找到名称对应的视图Bean解析视图
    }
}

我们在游览器访问view1即会跳转到对应的hello.jsp视图。

3. XmlViewResolver

它继承自 AbstractCachingViewResolver 抽象类,所以它也是支持视图缓存的。 XmlViewResolver 需要给定一个 xml 配置文件来定义视图的 bean 对象。在该文件中定义的每一个视图的 bean 对象都给定一个名字,然后 XmlViewResolver 将根据 Controller 处理器方法返回的逻辑视图名称到 XmlViewResolver 指定的配置文件中寻找对应名称的视图 bean 用于处理视图。该配置文件默认是 /WEB-INF/views.xml 文件,如果不使用默认值的时候可以在 XmlViewResolver 的 location 属性中指定它的位置。

这里需要明确的是,使用XmlViewResolver最终不一定需要输出xml视图

以下是使用 XmlViewResolver 的一个示例:

1. 在 SpringMVC 的配置文件中加入 XmlViewResolver 的 bean 定义。

使用 location 属性指定其配置文件所在的位置, order 属性指定当有多个 ViewResolver 的时候其处理视图的优先级。

<bean class="org.springframework.web.servlet.view.XmlViewResolver">
   <property name="location" value="/WEB-INF/views.xml"/>
   <property name="order" value="1"/>
</bean>

2. 在 XmlViewResolver 对应的配置文件中配置好所需要的视图定义。

在下面的代码中我们就配置了一个名为 hello 的 InternalResourceView ,其 url 属性为“ /index.jsp ”。

<bean id="hello" class="org.springframework.web.servlet.view.InternalResourceView">
   <property name="url" value="/WEB-UBF/view/hello.jsp"/>
</bean>

3. 配置web层控制器

@Controller
public class ViewController {
    @RequestMapping("view2")
    public String view2(){
        return "hello";//返回字符串直接为视图名称,解析器会找到名称对应的视图Bean解析视图
    }
}

类似于BeanNameViewResolver的实例,我们访问view2,XmlViewResolver会到/WEB-INF/views.xml中寻找相应id的视图完成解析。

5. ResourceBundleViewResolver

它继承自 AbstractCachingViewResolver ,但是它缓存的不是视图.和 XmlViewResolver 一样它也需要有一个配置文件定义逻辑视图名称和真正的 View 对象的对应关系,不同的是 ResourceBundleViewResolver 的配置文件是一个属性文件,而且必须是放在 classpath 路径下面的,默认情况下这个配置文件是在* classpath 根目录下的 views.properties 文件,如果不使用默认值的话,则可以通过属性 baseName 或 baseNames 来指定*。 baseName 只是指定一个基名称, Spring 会在指定的 classpath 根目录下寻找以指定的 baseName 开始的属性文件进行 View 解析,如指定的 baseName 是 base ,那么 base.properties 、 baseabc.properties 等等以 base 开始的属性文件都会被 Spring 当做 ResourceBundleViewResolver 解析视图的资源文件。 ResourceBundleViewResolver 使用的属性配置文件的内容类似于这样:

resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView
resourceBundle.url=/index.jsp
test.(class)=org.springframework.web.servlet.view.InternalResourceView
test.url=/test.jsp

对应与上述配置,spring会将其解析成如下Bean定义:

<bean id="resourceBundle" class="org.springframework.web.servlet.view.InternalResourceView">
   <property name="url" value="/index.jsp"/>
</bean>

<bean id="test" class="org.springframework.web.servlet.view.InternalResourceView">
   <property name="url" value="/test.jsp"/>
</bean>

接下来讲讲 Spring 通过 properties 文件生成 bean 的规则。它会把 properties 文件中定义的属性名称按最后一个点“ . ”进行分割,把点前面的内容当做是 bean 名称点后面的内容当做是 bean 的属性。这其中有几个特别的属性, Spring 把它们用小括号包起来了,这些特殊的属性一般是对应的 attribute ,但不是 bean 对象所有的 attribute 都可以这样用。其中 (class) 是一个,除了 (class) 之外,还有 (scope) 、 (parent) 、 (abstract) 、 (lazy-init) 。而除了这些特殊的属性之外的其他属性, Spring 会把它们当做 bean 对象的一般属性进行处理,就是 bean 对象对应的 property 。所以根据上面的属性配置文件将生成如下两个 bean 对象:

从 ResourceBundleViewResolver 使用的配置文件我们可以看出,它和 XmlViewResolver 一样可以解析多种不同类型的 View ,因为它们的 View 是通过配置的方式指定的,这也就意味着我们可以指定 A 视图是 InternalResourceView , B 视图是 JstlView 。

除了以上的视图解析器,常用的还有下面两个模板视图解析器:FreeMarkerViewResolver 、 VolocityViewResolver,在后面的文章会专门提到。



参考书籍:《Spring 3.x企业应用开发实战》

参考文章:http://www.tuicool.com/articles/RVb67r

时间: 2024-07-31 01:20:58

springMVC4(13)视图解析器分类详解的相关文章

AngularJS源码解析4:Parse解析器的详解

$ParseProvider简介 此服务提供者也是angularjs中用的比较多的,下面我们来详细的说下这个provider. function $ParseProvider() { var cache = {}; var $parseOptions = { csp: false, unwrapPromises: false, logPromiseWarnings: true }; this.unwrapPromises = function(value) { if (isDefined(val

详解Spring MVC 4之ViewResolver视图解析器

所有的We MVC框架都有一套它自己的解析视图的机制,Spring MVC也不例外,它使用ViewResolver进行视图解析,让用户在浏览器中渲染模型.ViewResolver是一种开箱即用的技术,能够解析JSP.Velocity模板和XSLT等多种视图. Spring处理视图最重要的两个接口是ViewResolver和View.ViewResolver接口在视图名称和真正的视图之间提供映射: 而View接口则处理请求将真正的视图呈现给用户.  1.几种常见的ViewResolver视图解析器

SSM之旅(二)--换个视图解析器FreeMarker

对于一些不写jsp的同学来说,freemarker是个不错的选择,什么是freeMarker,没错,他是一个动态模板引擎,并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件.具体啥的自己是了解. 1.想要引入freemarker,首先你需要引入jar包,毕竟他是一个java类库 <!--freeMarker依赖--><dependency> <groupId>

Java基础13:反射与注解详解

Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Oracle官方对反射的解释是 Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fi

【SpringMVC笔记】第五课 改进Handler处理器和视图解析器

第四课 已经对注解的映射器和适配器进行了改进. 接下来需要对Handler处理器和视图解析器进行改进. <!-- 配置handler处理器 --> <bean class="com.king.controller.UserController"></bean> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourc

SpringMVC自定义多视图解析器

实现通过请求url后缀判断返回值类型, 例如 localhost:8080/list 返回JSP页面, localhost:8080/list.json返回json格式数据 1.创建一枚举返回值类型 public enum ResultType { REDIRECT, JSP, JSON, XML } 2.创建自定义的viewResolver 1 public class JsonViewResolver implements ViewResolver { 2 3 private View vi

Apache Spark源码走读之13 -- hiveql on spark实现详解

欢迎转载,转载请注明出处,徽沪一郎 概要 在新近发布的spark 1.0中新加了sql的模块,更为引人注意的是对hive中的hiveql也提供了良好的支持,作为一个源码分析控,了解一下spark是如何完成对hql的支持是一件非常有趣的事情. Hive简介 Hive的由来 以下部分摘自Hadoop definite guide中的Hive一章 "Hive由Facebook出品,其设计之初目的是让精通SQL技能的分析师能够对Facebook存放在HDFS上的大规模数据集进行分析和查询. Hive大大

java虚拟机启动参数分类详解

官方文档见: http://docs.sun.com/source/819-0084/pt_tuningjava.html java启动参数共分为三类:其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容:其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容:其三是非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用: 一.标准参数中比较有用的: verbose -verbo

7.SpringMVC 配置式开发-ModelAndView和视图解析器

ModelAndView 1.Model(模型) 1.model的本质就是HashMap,向模型中添加数据,就是往HashMap中去添加数据 2.HashMap 是一个单向查找数组,单向链表数组 3.LinkedHashMap,本质是一个HashMap,但其将Entry进行了扩展,变成双向的了 2.View(视图) ModelAndView 内部通过 setViewName() 指定视图名称 这个视图名称对应一个视图对象,这个视图对象会被封装在ModelAndView中,传给视图解析器来解析 视