Springmvc中多视图解析器解析问题

最近被问到过几次关于springmvc多视图解析器解析的问题;总结一下。

1、问题:

假设我有两个jsp:

WEB-INF/html/a.jsp
WEB-INF/report/b.jsp

且我配置了视图解析器:

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="1">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="contentType" value="text/html"/>
        <property name="prefix" value="/WEB-INF/html/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="2">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="contentType" value="text/html"/>
        <property name="prefix" value="/WEB-INF/report/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

然后呢,我分别返回视图名为a和b;为什么a能找到,而b的时候是404;我配置了两个视图解析器,第一个找不到的话,第二个能找到啊?遇到过这个问题的朋友基本上会有类似的问题;

2、分析

扫描二维码关注公众号,回复: 569316 查看本文章

此处我们使用了InternalResourceViewResolver,其有一个buildView方法,该方法一定会创建一个View;所以呢View永远不为null(即使该jsp不存在);问题就是出在这;因为我们使用这个的时候默认是使用servlet forward转发的,此时并不知道该jsp是否存在。

3、解决方案:

3.1、最简单的办法是使用其viewNames属性,来指定一个是否可以处理的规则;

<property name="viewNames" value="html*"/>
<property name="viewNames" value="report*"/>

 如上两个的意思是对html或report开头的视图名进行处理,比如返回的视图名为html/a 那么会交给viewNames为html*的那个解析器处理;支持的规则可以查看javadoc。

3.2、内容协商,根据请求时的MediaType来决定使用哪个View;比如根据不同的MediaType决定是JSON/XML/HTML展示时;可以搜索ContentNegotiatingViewResolver了解;

以上的方式对于请求的MediaType一样,且视图名没有规则时一点用没有。

3.3、如果仅有几个不同的视图需要特殊处理;可以考虑直接返回View对象进行处理;而直接不走ViewResolver;

3.4、如果以上都不满足;那只能自己实现自己相应的ViewResolver,可以覆盖两个方法进行处理:

3.4.1、覆盖UrlBasedViewResolver子类的canHandle;来决定哪些视图名不需要当前ViewResolver进行处理;自己可以得到prefix + suffix进行判断具体的视图页面是否存在,当然这个可能会存在性能问题;考虑做缓存。

猜你喜欢

转载自jinnianshilongnian.iteye.com/blog/1985405