ContentNegotiatingViewResolver实现多视图

2014/09/27 3177点热度 0人点赞 0条评论

    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的处理流程(左上角入口)

yxkong

这个人很懒,什么都没留下

文章评论