spring视图解析器ViewResolver

今天同事写代码,发现写的freemarker的视图没有找到,但是报的是jstl视图解析器文件路径没有找到的错误。

然后我们顺势研究了一下机制和源码,发现freemarkerView会判断文件是否存在,而jstlView则不会。

解析器配置和分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<bean id="jstlViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver" parent="viewResolver">
<property name="order" value="2" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
</bean>
<bean id="freemarkerResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" parent="viewResolver">
<!--<property name="cache" value="true"/> -->
<property name="order" value="1" />
<property name="viewNames">
<array>
<value>*.ftl</value>
</array>
</property>
<!-- <property name="suffix" value=".ftl" /> -->
<property name="requestContextAttribute" value="request" />
<property name="exposeSpringMacroHelpers" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="allowSessionOverride" value="true" />
<property name="contentType" value="text/html;charset=utf-8" /><!--编码 -->
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
</bean>

视图解析器的配置如上面所示,视图解析是链式的,如果一个视图解析器没有找到对应的viewName,则开始找第二的解析器。所谓的1、2,就是上面配置的order。从小到大,越小的优先级越高

源码在DisptcherServlet类的resolveViewName的方法中

jstlView和FreeMarkerView不同之处

UrlBasedViewResolver 和 jstlView,不对视图文件的存在性进行判断

可以看到UrlBasedViewResolver加载视图时会进行checkResource,判断资源是否存在,而jstlView中的是怎么实现的呢

jstlView的checkResource是继承自AbstractUrlBasedView类的,这个类中的方法是直接return true的!

也就是说,jstlView并不保证视图文件一定存在,而是直接创建一个View对象

FreeMarkerViewResolver 和 FreeMarkerView 会检查视图文件是否存在

FreeMarkerViewResolver 虽然也是集成自UrlBasedViewResolver类,但是我们使用的视图是FreeMarkerView,它重写了checkResource方法,如果文件不存在,返回false,则ViewResolver返回null,DisptcherServlet继续在下一个视图解析器中寻找View


参考文档

http://bbs.51cto.com/thread-1133128-1.html