Spring mvc 使用多种viewResolver的问题

问题描述

问题大概是这样的:我配置了两个viewResovler: <bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath" value="/WEB-INF/velo/"/> <property name= "velocityProperties"> <props> <prop key="input.encoding">utf-8</prop> <prop key="output.encoding">utf-8</prop> </props> </property> </bean><bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="cache" value="false"/> <property name="prefix" value=""/> <property name="suffix" value=".vm"/> <property name="contentType"><value>text/html;charset=UTF-8</value></property> <property name="exposeSpringMacroHelpers" value="true"/> <property name="order"><value>0</value></property></bean> <bean id="JSPviewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="cache" value="false"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> <property name="contentType"><value>text/html;charset=UTF-8</value></property> <property name="order"><value>1</value></property></bean>目的是为了,请求多种视图,viewResovler的order如上图使用@RequestMapping(value ="/welcome/user")public ModelAndView welcome(HttpServletRequest request,HttpServletResponse response,ModelMap modelMap) {return new ModelAndView("welcome",modelMap);//普通转向}第一次http://localhost:8080/Prj/welcome/user 请求/WEB-INF/velo/目录底下的welcome.vm文件可以正常访问当我把java代码修改成这样@RequestMapping(value ="/welcome/user")public ModelAndView welcome(HttpServletRequest request,HttpServletResponse response,ModelMap modelMap) {return new ModelAndView("welcome",modelMap);//普通转向}并且把jspresovler的order改成0,把velocity的resovler改成1目的就是为了在/WEB-INF/jsp/目录下找不到welcome.jsp文件,按理说servlet会继续在另外一个resovler里面来查找.vm文件应该是去找 /WEB-INF/veclo/目录底下寻找 welcome.vm文件,但是当我请求上面的请求的时候,tomcat提示404错误,后台打印 说找不到welcome.jsp文件是什么原因?各位大虾?补充:当我把两个order都设为0的时候,也是可以找到的

解决方案

public boolean checkResource(Locale locale) throws Exception {return true;}罪魁祸首 就是spring实现该方法时返回true,这样相当于view总是存在,从而导致其余视图解析器无法得到解析机会。 覆盖该方法,应该就可以了。 public class IcomJstlView extends JstlView {public boolean checkResource(Locale locale) throws Exception {File file = new File(this.getServletContext().getRealPath("/")+getUrl());return file.exists();//判断该jsp页面是否存在}}
解决方案二:
不错
解决方案三:
我没有用过两个视图,所以看了一下源码,看代码:DispatchServlet.java中 doDispatch最后是调用render方法做视图渲染的:protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)throws Exception {// Determine locale for request and apply it to the response.Locale locale = this.localeResolver.resolveLocale(request);response.setLocale(locale);View view = null;if (mv.isReference()) {// We need to resolve the view name.view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);if (view == null) {throw new ServletException("Could not resolve view with name '" + mv.getViewName() +"' in servlet with name '" + getServletName() + "'");}}else {// No need to lookup: the ModelAndView object contains the actual View object.view = mv.getView();if (view == null) {throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +"View object in servlet with name '" + getServletName() + "'");}}// Delegate to the View object for rendering.if (logger.isDebugEnabled()) {logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");}view.render(mv.getModelInternal(), request, response);}mv.isReference() 是说你是不是用名字代替传递一个View实例给ModelAndView对象,你传递的都是名字,所以再看protected View resolveViewName(String viewName, Map model, Locale locale, HttpServletRequest request)throws Exception {for (Iterator it = this.viewResolvers.iterator(); it.hasNext();) {ViewResolver viewResolver = (ViewResolver) it.next();View view = viewResolver.resolveViewName(viewName, locale);if (view != null) {return view;}}return null;}this.viewResolvers 这个就是你配的两个viewResolvers,分别试着去创建View,再看看创建View的代码public View resolveViewName(String viewName, Locale locale) throws Exception {if (!isCache()) {logger.warn("View caching is SWITCHED OFF -- DEVELOPMENT SETTING ONLY: This can severely impair performance");return createView(viewName, locale);}else {Object cacheKey = getCacheKey(viewName, locale);synchronized (this.viewCache) {View view = (View) this.viewCache.get(cacheKey);if (view == null) {// Ask the subclass to create the View object.view = createView(viewName, locale);this.viewCache.put(cacheKey, view);if (logger.isTraceEnabled()) {logger.trace("Cached view [" + cacheKey + "]");}}return view;}}}最终落实到 createView,因为你的两个viewResolvers都是实现的 UrlBasedViewResolver,所以看UrlBasedViewResolver这里面的buildView方法就行了protected AbstractUrlBasedView buildView(String viewName) throws Exception {AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());view.setUrl(getPrefix() + viewName + getSuffix());String contentType = getContentType();if (contentType != null) {view.setContentType(contentType);}view.setRequestContextAttribute(getRequestContextAttribute());view.setAttributesMap(getAttributesMap());return view;}并没有看到有试图去找(getPrefix() + viewName + getSuffix())对应的文件,所以并不会返回null,所以只查找了jsp就没有查找fm了Spring并不会去检查你这个文件(welcome.jsp)是否存在,只是最后渲染的时候交给给自处理 VelocityViewResolver交给Velocity处理,InternalResourceViewResolver交给 servlet request 处理也可以说UrlBasedViewResolver找出来的View没有被Spring容器管理,所以他不知道有没有如果想实现你的功能,可以扩展DispatchServlet的resolveViewName方法,例如:class MyDispatcherServlet extends DispatcherServlet {private List viewResolvers;@Overrideprotected View resolveViewName(String viewName, Map model, Locale locale,HttpServletRequest request) throws Exception {WebApplicationContext context = getWebApplicationContext();for (Iterator it = this.viewResolvers.iterator(); it.hasNext();) {ViewResolver viewResolver = (ViewResolver) it.next();View view = viewResolver.resolveViewName(viewName, locale);if (view != null) {if (view instanceof AbstractUrlBasedView) {try {Resource resource = context.getResource(((AbstractUrlBasedView) view).getUrl());if (resource == null) {// logcontinue;}} catch (Exception e) {// logcontinue;}}return view;}}return null;}}当然你要初始化viewResolvers 因为DispatchServlet中该属性为私有的网上找到的:如果为DispatcherServlet指定多个ViewResolver的话,不要给予InternalResour- ceViewResolver以及其他UrlBasedViewResolver子类过高的优先级,因为这些ViewResolver即使找不到相应的视图,也不会返回null以给我们轮询下一个ViewResolver的机会,这样,我们所指定的其他ViewResolver实际上就形同虚设。合理的处理方式是,给予ResourceBundleView- Resolver或者XmlViewResolver这种能够通过返回null以表明无法找到相应视图的ViewResolver较高的优先级,而只是将InternalResourceViewResolver(或者其他类似行为的ViewResolver)添加为最低优先级ViewResolver,以作为DispatcherServlet的后备查找对象。

时间: 2024-09-21 19:32:13

Spring mvc 使用多种viewResolver的问题的相关文章

Spring MVC入门 —— 跟开涛学SpringMVC

2014-05-14 23:22:27 第二章 Spring MVC入门 -- 跟开涛学SpringMVC  浏览(84979)|评论(12)   交流分类:Java|笔记分类: 跟开涛学Spring--  2.1.Spring Web MVC是什么 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring

Spring MVC 详解

第一章 Web MVC简介Web MVC简介 1.1.Web开发中的请求-响应模型:   在Web世界里,具体步骤如下: 1.  Web浏览器(如IE)发起请求,如访问http://sishuok.com 2.  Web服务器(如Tomcat)接收请求,处理请求(比如用户新增,则将把用户保存一下),最后产生响应(一般为html). 3.web服务器处理完成后,返回内容给web客户端(一般就是我们的浏览器),客户端对接收的内容进行处理(如web浏览器将会对接收到的html内容进行渲染以展示给客户)

spring mvc

作者:赵磊 博客:http://elf8848.iteye.com   目录 一.前言 二.spring mvc 核心类与接口 三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 六.springMVC-mvc.xml 配置文件片段讲解 七.spring mvc 如何访问到静态的文件,如jpg,js,css 八.spring mvc 请求如何映射到具体的Action中的方法 九.spring mvc 

Spring MVC 教程,快速入门,深入分析(转载)

作者:赵磊 博客:http://elf8848.iteye.com 下载: Spring的官方下载网址是:http://www.springsource.org/download    (本文使用是的Spring 3.0.5版本) 目录  一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 六.springMVC-mvc.xml 配置文件片段讲解 七.sp

Spring MVC配置介绍

一.Spring MVC 纵览 Spring MVC就是Spring框架对MVC设计模式的实现,通过Spring MVC ,我们可以快速的构建灵活.松耦合的web服务.再具体介绍Spring MVC 之前,我们先看一下它的请求处理过程: 1.1 springMVC 的请求过程 1. 请求会首先发送到DispatchServlet,这是spring的前置Servlet,它会接收请求并转发给spring的MVC controller,也就是业务controller 2. DispatchServle

Spring MVC 中 如何解析视图及视图解析的详细流程

SpringMVC 如何解析视图 请求处理方法返回值类型是 String ModelAndView View SpringMVC都会奖其转化为ModelAndView对象,再给ViewResolver,最后变成视图对象,如JSP.JSTL.PDF等. 视图和视图解析器 请求处理方法执行完成后,最终返回一个ModelAndView对象.对于那些返回String,View和ModeMap等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView对象,它包含了逻辑名和模

Spring MVC快速上手教程

Spring Framework可以被使用在很多场合之中,考虑到目前大多数Java EE的项目是B/S结构的,所以这里的快速上手教程会以Spring MVC为切入点,用最简单的代码一步一步来实现一个图书列表的页面. 在正式动手之前需要做一些准备工作,先安装并设置好JDK 1.5和Tomcat 5,关于数据库及其访问方式可以根据个人习惯进行选择,教程中使用MySQL数据库和Hibernate(映射由Hibernate Annotation实现).请将实际使用到的jar文件复制到WEB-INF/li

java学习笔记 ContextLoaderListener和Spring MVC中的DispatcherServlet

DispatcherServlet介绍 DispatcherServlet是Spring前端控制器的实现,提供Spring Web MVC的集中访问点,并且负责职责的分派,与Spring IoC容器无缝集成,从而可以获得Spring的所有好处. DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下: 1.文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析: 2.通过HandlerMapping,将请求映射到

深入整体分析Spring MVC framework

在当今的MVC framework里,似乎Webwork2逐渐成为主流, Webwork2+SpringFramework的组合变得越来越流行.这似乎意味着Spring自带的MVC framework远比Webwork2差,所以大家纷纷用Webwork2来代替.确实,Spring的MVC framework不算是整个Spring的核心部件,但它的威力却超过了很多人的想象.很多人包括xiecc认为Spring的MVC framework是非常优秀的,甚至比Webwork2更优秀. 下面列举一下Sp