spring在解析视图的时候有两个重要的接口:ViewResolver 和 View
ViewResolver 中只有一个方法 resolveViewName ,提供 view name 和 实际 view的映射;View 中两个方法 getContentType 和 render ,解析请求中的参数并把这个请求处理成某一种 View.
说白了,就是ViewResolver 负责怎么去解析, 而View只代表一种 视图层的技术。
对于一个请求,应该返回什么样的视图是 ViewResolver 来决定的,spring3.0提供的 ViewResolver 包括AbstractCachingViewResolver,XmlViewResolver,ResourceBundleViewResolver,UrlBasedViewResolver,InternalResourceViewResolver,VelocityViewResolver/FreeMarkerViewResolver,ContentNegotiatingViewResolver等。从字面意思我们大致就可以猜出起用途。
我们平时使用ResourceBundleViewResolver或者InternalResourceViewResolver来返回JSP页面,他们就是其中的两个 ViewResolver
<!-- 根据客户端的不同的请求决定不同的view进行响应, 如 /demo/find.json /demo/find.xml -->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!--设置视图解析排序-->
<property name="order" value="1" />
<!-- 设置在没有扩展名时,即: "/user/find" 时的默认展现形式 -->
<property name="defaultContentType" value="text/html" />
<!-- 是否从扩展名中取mediaType(如xxx.xml,xxx.html),与mediaTypes匹配 -->
<property name="favorPathExtension" value="true" />
<!-- 默认值:format,当favorParameter=true,根据parameterName来获取mediaType,与mediaTypes匹配 -->
<property name="parameterName" value="mediaType" />
<!-- 是否从请求的url路径中获取 mediaType(如:/xxx/xxx?mediaType=xml),与mediaTypes匹配 -->
<property name="favorParameter" value="true" />
<!-- 是否忽略请求头里的Accept Header属性,为了解决不同浏览器中对应不同的accept -->
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes">
<map>
<entry key="html" value="text/html" />
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="txt" value="text/plain" />
<entry key="xls" value="application/vnd.ms-excel" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller" ref="xStreamMarshaller" />
</bean>
</list>
</property>
<property name="viewResolvers">
<list>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/jsp/" />
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
</list>
</property>
</bean>
1. spring检查setFavorPathExtension(boolean) ,如果这个属性为true(默认为true),检查请求的后缀名,来返回一种 mediaType ,而后缀名和mediaType是通过ContentNegotiatingViewResolver 配置中的mediaTypes指定的。
2.spring检查 setFavorParameter(boolean) 这个属性是否为true(默认为false),而如果你打开这个属性,那么默认的参数名应为 format ,spring通过你传过去的参数决定返回哪种mediaType。
3.如果前两步没有找到合适的mediaType,则使用defaultViews设置的默认值显示。
4.如果前三步都没有找到合适的mediaType,并且 ignoreAcceptHeader 这个属性为false(默认为false),spring则根据请求头里面设置的ContentType来找适合的mediaType。
最后一点别忘了在web.xml中配置
<servlet>
<description>spring mvc 分发器</description>
<servlet-name>framework</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- spring mvc 配置文件
给DispatcherServlet的父类FrameworkServlet属性contextConfigLocation赋值
包含容器启动时所要执行的内容
如果不配置init-param参数,在服务器启动时,会在WEB-INF目录下查找命名规则为<servlet-name>-servlet.xml的文件,对应到这里就是framework-servlet.xml文件
-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springmvc-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>framework</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>framework</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>framework</servlet-name>
<url-pattern>*.xml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>framework</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
如此,前台可以根据demo/find.xml或者demo/find.json获取不同的数据
后台
@RequestMapping(value = "find")
public ModelAndView find() {
Map<String,Object> map = HashMap<String,Object>();
map.put("flag", "succ");
map.put("message", "请求成功!");
return new ModelAndView("demo/view",map);
}
ContentNegotiatingViewResolver的处理流程(左上角入口)