`
xiaoyaocao
  • 浏览: 276058 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

【转】 SpringMVC ViewResolver查找序列

阅读更多

虽然我们在之前的示例中一直都是使用一个InternalResourceViewResolver进行视图查找,但这并不意味着每个基于 Spring MVC的Web应用程序只能使用一个ViewResolver。实际上,Dispatcher- Servlet不但可以接受多个HandlerMapping以处理Web请求到具体Handler的映射,也可以接受多个ViewResolver以处理视图的查找。

DispatcherServlet初始化时,将根据类型扫描自己的WebApplicationContext中定义的 ViewResolver。如果查找到存在多个ViewResolver的定义,DispatcherServlet将根据这些ViewResolver 的优先级进行排序,然后当需要根据逻辑视图名查找具体的View实例的时候,将按照排序后的顺序遍历这些ViewResolver,只要期间任何一个 ViewResolver返回非空的View实例,当前查找即告结束。如果DispatcherServlet没能在当前的 WebApplicationContext中找到任何的ViewResolver定义,它将使用 InternalResourceViewResolver作为默认的ViewResolver使用。

ViewResolver的优先级的指定使用Ordered接口作为标准,这已经成为Spring框架内设定优先级方式的惯例了。假设我们希望主要使用ResourceBundleViewResolver进行逻辑视图名到具体View实例的查找,如果没能找到,再寻求 InternalResourceViewResolver的帮助。我们可以在Dispatcher- Servlet的WebApplicationContext中添加如下配置内容:

 

Xml代码

 

01 <bean id="resourceBundleViewResolver"
02  class="org.springframework.Web.servlet.view.
03 ResourceBundleViewResolver">
04 <property name="order" value="1"></property>
05 </bean>
06 <bean id="viewResolver"
07 class="org.springframework.Web.servlet.view.
08 InternalResourceViewResolver">
09 <property name="prefix" value="/WEB-INF/jsp/"/>
10 <property name="suffix" value=".jsp"/>
11 </bean>

相应ViewResolver的bean定义对应的id或者name属性值是任意的,DispatcherServlet将按照类型来获取ViewResolver。如果没有为某个ViewResolver指定order值的话,默认值为Integer.MAX_ VALUE,对应的是最低优先级。

如果为DispatcherServlet指定多个ViewResolver的话,不要给予 InternalResour- ceViewResolver以及其他UrlBasedViewResolver子类过高的优先级,因为这些ViewResolver即使找不到相应的视图,也不会返回null以给我们轮询下一个ViewResolver的机会,这样,我们所指定的其他ViewResolver实际上就形同虚设。合理的处理方式是,给予ResourceBundleView- Resolver或者XmlViewResolver这种能够通过返回null以表明无法找到相应视图的ViewResolver较高的优先级,而只是将 InternalResourceViewResolver(或者其他类似行为的ViewResolver)添加为最低优先级ViewResolver,以作为DispatcherServlet的后备查找对象。

----------------------------------------------------------------------------------------------

13.5. 视图与视图解析

所有web应用的MVC框架都有它们定位视图的方式。 Spring提供了视图解析器供你在浏览器显示模型数据,而不必被束缚在特定的视图技术上。 Spring内置了对JSP,Velocity模版和XSLT视图的支持。第 14 章 集成视图技术这一章详细说明了Spring如何与不同的视图技术集成。

ViewResolverView是Spring的视图处理方式中特别重要的两个接口。 ViewResolver提供了从视图名称到实际视图的映射。 View处理请求的准备工作,并将该请求提交给某种具体的视图技术。

13.5.1. 视图解析器(ViewResolver

正如前面(第 13.3 节 “控制器”)所讨论的, SpringWeb框架的所有控制器都返回一个ModelAndView实例。 Sprnig中的视图以名字为标识,视图解析器通过名字来解析视图。Spring提供了多种视图解析器。我们将举例加以说明。

表 13.4. 视图解析器

 

ViewResolver 描述

 

AbstractCachingViewResolver 抽象视图解析器实现了对视图的缓存。在视图被使用之前,通常需要进行一些准备工作。 从它继承的视图解析器将对要解析的视图进行缓存。
XmlViewResolver XmlViewResolver实现ViewResolver,支持XML格式的配置文件。 该配置文件必须采用与Spring XML Bean Factory相同的DTD。默认的配置文件是 /WEB-INF/views.xml
ResourceBundleViewResolver ResourceBundleViewResolver实现ViewResolver, 在一个ResourceBundle中寻找所需bean的定义。 这个bundle通常定义在一个位于classpath中的属性文件中。默认的属性文件是views.properties
UrlBasedViewResolver UrlBasedViewResolver实现ViewResolver, 将视图名直接解析成对应的URL,不需要显式的映射定义。 如果你的视图名和视图资源的名字是一致的,就可使用该解析器,而无需进行映射。
InternalResourceViewResolver 作为UrlBasedViewResolver的子类, 它支持InternalResourceView(对Servlet和JSP的包装), 以及其子类JstlViewTilesView。 通过setViewClass方法,可以指定用于该解析器生成视图使用的视图类。 更多信息请参考UrlBasedViewResolver的Javadoc。
VelocityViewResolver /FreeMarkerViewResolver 作为UrlBasedViewResolver的子类, 它能支持VelocityView(对Velocity模版的包装)和FreeMarkerView以及它们的子类。

举例来说,当使用JSP作为视图层技术时,就可以使用UrlBasedViewResolver。 这个视图解析器会将视图名解析成URL,并将请求传递给RequestDispatcher来显示视图。

<bean id="viewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/></bean>当返回的视图名为test时, 这个视图解析器将请求传递给RequestDispatcherRequestDispatcher再将请求传递给/WEB-INF/jsp/test.jsp

当在一个web应用中混合使用不同的视图技术时,可以使用ResourceBundleViewResolver

<bean id="viewResolver"> <property name="basename" value="views"/> <property name="defaultParentView" value="parentView"/></bean>ResourceBundleViewResolver通过basename所指定的ResourceBundle解析视图名。 对每个待解析的视图,ResourceBundle里的[视图名].class所对应的值就是实现该视图的类。 同样,[视图名].url所对应的值是该视图所对应的URL。 从上面的例子里能够发现,可以指定一个parent view,其它的视图都可以从parent view扩展。用这种方法,可以声明一个默认的视图。

关于视图缓存的注意事项 - 继承AbstractCachingViewResolver的解析器可以缓存它曾经解析过的视图。 当使用某些视图技术时,这可以大幅度的提升性能。 也可以关掉缓存功能,只要把cache属性设成false就可以了。 而且,如果需要在系统运行时动态地更新某些视图(比如,当一个Velocity模板被修改了), 可以调用removeFromCache(String viewName, Locale loc)方法来达到目的。

13.5.2. 视图解析链

Spring支持多个视图解析器一起使用。可以把它们当作一个解析链。 这样有很多好处,比如在特定情况下重新定义某些视图。 定义视图解析链很容易,只要在应用上下文中定义多个解析器就可以了。 必要时,也可以通过order属性来声明每个解析器的序列。 要记住的是,某个解析器的order越高, 它在解析链中的位置越靠后。

下面这个例子展示了一个包含两个解析器的解析链。 一个是InternalResourceViewResolver,这个解析器总是被自动的放到链的末端。 另一个是XmlViewResolver,它支持解析Excel视图(而InternalResourceViewResolver不可以)。

01 <bean id="jspViewResolver">
02 <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
03 <property name="prefix" value="/WEB-INF/jsp/"/>
04 <property name="suffix" value=".jsp"/></bean><bean id="excelViewResolver">
05 <property name="order" value="1"/>
06 <property name="location" value="/WEB-INF/views.xml"/>
07 </bean>
08 <!-- in views.xml -->
09 <beans>
10  <bean name="report"/>
11 </beans>

 

如果某个解析器没有找到合适的视图,Spring会在上下文中寻找是否配置了其它的解析器。 如果有,它会继续进行解析,否则,Srping会抛出一个Exception

要记住,当一个视图解析器找不到合适的视图时,它可能 返回null值。 但是,不是每个解析器都这么做。这是因为,在某些情况下,解析器可能无法侦测出符合要求的视图是否存在。 比如,InternalResourceViewResolver在内部调用了RequestDispatcher。 请求分发是检查一个JSP文件是否存在的唯一方法,不幸的是,这个方法只能用一次。 同样的问题在VelocityViewResolver和其它解析器中也有。 当使用这些解析器时,最好仔细阅读它们的Javadoc,看看需要的解析器是否无法发现不存在的视图。 这个问题产生的副作用是,如果InternalResourceViewResolver解析器没有放在链的末端, InternalResourceViewResolver后面的那些解析器根本得不到使用, 因为InternalResourceViewResolver总是返回一个视图!

13.5.3. 重定向(Rediret)到另一个视图

在前面我们提到过,一个控制器通常会返回视图名,然后由视图解析器解析到某种视图实现。 对于像JSP这样实际上由Servlet/JSP引擎处理的视图, 我们通常使用InternalResourceViewResolverInternalResourceView。 这种视图实现最终会调用Servlet API的RequestDispatcher.forward(..)方法或RequestDispatcher.include()方法将用户指向最终页面。 对于别的视图技术而言(比如Velocity、XSLT等等),视图本身就会生成返回给用户的内容。

有些时候,在视图显示以前,我们可能需要给用户发一个HTTP redirect重定向指令。 比如,一个控制器成功的处理了一个表单提交(数据以HTTP POST的方式发送),它最终可能委托给另一个控制器来完成剩下的工作。 在这种情况下,如果我们使用内部forward,接手工作的那个控制器将会得到所有以POST方式提交的表单数据, 这可能会引起潜在的混淆,干扰那个控制器的正常工作。 另一个在显示视图之前返回HTTP redirect的原因是这可以防止用户重复提交同一表单。 具体一点讲,浏览器先用POST的方式提交表单,然后它接收到重定向的指令,它继续用GET的方式去下载新的页面。 从浏览器的角度看,这个新的页面不是POST的返回结果,而是GET的。 这样,用户不可能在点击刷新的时候不小心再次提交表单,因为刷新的结果是再次用GET 去下载表单提交后的结果页面,而不是重新提交初始的POST数据。

13.5.3.1. RedirectView

在控制器中强制重定向的方法之一是让控制器创建并返回一个Spring的RedirectView的实例。 在这种情况下,DispatcherServlet不会使用通常的视图解析机制, 既然它已经拿到了一个(重定向)视图,它就让这个视图去完成余下的工作。

RedirectView会调用HttpServletResponse.sendRedirect()方法, 其结果是给用户的浏览器发回一个HTTP redirect。所有的模型属性都被转换成以HTTP请求的访问参数。 这意味着这个模型只能包含可以被简便的转换成string形式的HTTP请求访问参数的对象,比如String或者可以被转换成String的类型。

如果使用RedirectView视图,并且它是由控制器创建的, 重定向的URL最好是用Spring所提供的IoC功能注射到控制器中。 这样这个URL就可以和视图名一起在上下文中被声明,而不是固化在控制器内。

13.5.3.2. redirect:前缀

尽管使用RedirectView帮我们达到了目的,但是如果控制器生成RedirectView的话, 控制器不可避免地要知道某个请求的结果是让用户重定向到另一个页面。这不是最佳的实现,因为这使得系统不同模块之间结合得过于紧密。 其实控制器不应该过问返回结果是如何生成的,通常情况下,它应该只关心注入给它的视图名称。

解决上述问题的方法是依靠redirect:前缀。 如果返回的视图名包含redirect:前缀,UrlBasedViewResolver (以及它的子类) 会知道系统要生成一个HTTP redirect。 视图名其余的部分会被当作重定向URL。

这样做的最终结果跟控制器返回RedirectView是一样的,但现在控制器只需要和逻辑上的视图名打交道。 redirect:/my/response/controller.html这个逻辑视图名中的URL是当前servlet context中的相对路径。 与之相比,redirect:http://myhost.com/some/arbitrary/path.html中的URL是绝对路径。 重要的是,只要这个重定向视图名和其他视图名以相同的方式注入到控制器中,控制器根本不知道重定向是否发生。

13.5.3.3. forward:前缀

类似的,我们也可以使用包含有forward:前缀的视图名。 这些视图名会被UrlBasedViewResolver和它的子类正确解析。 解析的内部实现是生成一个InternalResourceView, 这个视图最终会调用RequestDispatcher.forward()方法,将forward视图名的其余部分作为URL。 所以,当使用InternalResourceViewResolver/InternalResourceView, 并且你所用的视图技术是JSP时,你没有必要使用这个前缀。 但是,当你主要使用其它的视图技术,但仍需要对Servlet/JSP engine处理的页面强制forward时, 这个forward前缀还是很有用的(但就这个问题而言,如果不想使用forward前缀,也可以使用视图解析链)。

redirect:前缀一样,如果含有forward前缀的视图名和其他视图名一样被注入控制器, 控制器根本不需要知道在处理响应的过程中是否发生任何特殊情况。

 

原文出处:http://www.dofind.net/prodevelop/32.html

分享到:
评论

相关推荐

    springMVC-jar包

    5. **视图解析器(ViewResolver)**:负责根据返回的视图名查找对应的视图模板,如JSP、Thymeleaf或FreeMarker等。 6. **拦截器(Interceptor)**:SpringMVC允许定义拦截器,可以在请求处理前后执行一些通用操作,...

    springmvc课堂笔记

    - **实现方式**:使用`@ResponseBody`注解将Java对象序列化为JSON字符串,或使用`@RequestBody`注解将JSON字符串反序列化为Java对象。 ##### 6.5 RESTful支持 - **实现方式**:通过`@RequestMapping`指定HTTP方法和...

    从源码的角度来看SpringMVC.zip

    SpringMVC提供了多种视图解析器,如`InternalResourceViewResolver`用于JSP,`BeanNameViewResolver`则根据视图名称直接查找bean。 7. **Model**:模型数据,存储在ModelAndView中,用于传递到视图进行渲染。模型...

    跟开涛学SpringMVC(6.2)SpringMVC3强

    通过配置`ViewResolver`,我们可以指定如何根据返回的视图名来查找和渲染实际的视图。 8. **异常处理**: SpringMVC提供了优雅的异常处理机制,允许我们用注解定义全局或特定异常的处理器。`@ExceptionHandler`注解...

    SpringMVC案例所有源码

    7. **ViewResolver**:视图解析器,根据逻辑视图名查找实际视图资源。 8. **Interceptor**:拦截器,允许在请求处理前后执行自定义逻辑,如权限检查、日志记录等。 9. **JSON和fastJson**:在标签中提到了这两个...

    看透SpringMVC源代码-分析与实践

    6. **ViewResolver**:视图解析器根据视图名称查找实际的视图(如JSP、FreeMarker等),并负责渲染结果。 7. **Interceptor**:拦截器可以预处理请求和后处理响应,例如权限校验、日志记录等,通过实现...

    《一头扎进SpringMvc》第四讲 源码

    6. **ViewResolver**:视图解析器负责根据ModelAndView中的视图名查找并实例化实际的视图。例如,JstlView或InternalResourceViewResolver。 7. **Model**:模型是数据的容器,用于在Controller和视图之间传递数据...

    手写SpringMVC 源码

    7. **ViewResolver**:视图解析器,根据给定的视图名查找实际的视图对象,如JSP、FreeMarker或Thymeleaf。 8. **Interceptor(拦截器)**:类似于AOP切面,可以在请求处理前、后进行额外的操作,如权限验证、日志...

    SpringMVC流程分析

    SpringMVC是Java EE开发中非常流行的轻量级框架,它是Spring框架的一部分,用于构建Web应用。SpringMVC采用了模型-视图-控制器(MVC)设计模式,能够将Web层进行清晰的分层,极大地提高了应用开发的效率和扩展性。...

    SpringMVC jar包

    6. **视图解析器(ViewResolver)**:SpringMVC中的组件,负责根据返回的视图名查找实际的视图资源,如JSP、Thymeleaf或FreeMarker模板。 7. ** ModelAndView**:它是一个容器,包含模型数据和视图信息。Controller...

    springmvc所需jar包

    - DispatcherServlet根据请求信息(如URL、HTTP方法)查找HandlerMapping。 - HandlerMapping找到对应的Handler(处理器,通常为Controller)。 - HandlerAdapter执行Handler并返回ModelAndView对象。 - ...

    springmvc_ch2 源代码

    Spring MVC 会通过 `RequestMappingHandlerMapping` 查找匹配的处理方法,并通过 `RequestMappingHandlerAdapter` 进行调用。 此外,`HandlerExceptionResolver` 处理未被捕获的异常,提供了一种统一的错误处理机制...

    SpringMVC +Mybatis+Spring+oscache配置文件

    2. **ViewResolver**:配置视图解析器,如`InternalResourceViewResolver`,用于将处理器返回的逻辑视图名转换为实际的视图资源。 3. **Controller**:定义控制器Bean,如`@Controller`注解的类,处理特定的HTTP请求...

    springmvc框架

    3. DispatcherServlet查找与请求URL匹配的HandlerMapping(处理器映射器),该组件负责将URL映射到具体的处理器(Controller)。 4. HandlerMapping找到对应的Controller后,会创建一个Controller实例,并调用其对应...

    spingmvc独立运行jar包

    6. **ViewResolver**:视图解析器根据ModelAndView中的视图名查找并返回具体的View实例,如JSP、Freemarker、Thymeleaf等。 7. **视图技术**:Spring MVC支持多种视图技术,如JSP、FreeMarker、Thymeleaf等,用于...

    springmvc

    - DispatcherServlet 查找合适的 HandlerMapping(处理器映射器)以确定处理请求的 Controller 方法。 - HandlerAdapter(处理器适配器)执行 Controller 方法,传递请求参数和模型数据。 - Controller 处理业务...

    spring in action mvc 第四版 中文版

    - ViewResolver:视图解析器,根据逻辑视图名查找并返回实际的View对象。 - ModelAndView:用于在Controller和View之间传递数据。 2. **Controller编程** - @Controller:标记一个类作为Spring MVC的Controller...

    涵盖Java从基础到高级的知识点以及重要的求职面试题

    - **枚举**:最简洁有效的方式,防止反序列化创建新实例。 ##### 2. **适配器模式** 适配器模式使得一个接口不兼容的类可以一起工作。主要分为三类: - **类适配器**:通过继承源类和目标接口来实现。适用于源类...

    spring学习文档及源码笔记

    - Jackson 或 Gson:JSON 序列化与反序列化,用于 REST API。 - Spring Security:提供认证和授权功能。 9. **源码分析** - 学习 Spring MVC 的源码有助于理解其内部机制,例如 DispatcherServlet 如何分发请求...

Global site tag (gtag.js) - Google Analytics