日期:2014-05-16  浏览次数:20817 次

SpringMVC中内容协商【统一资源多种展现json xml html】

????? 在我们实际的开发中,往往需要SpringMVC服务提供多种的格式的数据。如:JSON、XML、HTML

当然我们知道SpringMVC已经提供了很多种转换器,供我们使用将数据转换成我们想要的数据格式。但是服务者怎么知道使用者,想要使用哪种数据格式哪?这就使用到了SpringMVC中的内容协商。

既然是内容协商,那么使用者肯定会告诉服务者,你给我返回什么类型的数据。使用者可以通过如下方式通知服务者。

一、内容协商

??? 1、使用参数

????

/userController/getUser?format=json
/userController/getUser?format=xml

??? 2、使用扩展名

?

???

/userController/getUser.html
/userController/getUser.json
/userController/getUser.xml

??? 3、使用http的Request Headers中的Accpet

?

???

GET /userController/getUser HTTP/1.1
Accept: application/xml                 //将返回xml格式数据

GET /userController/getUser HTTP/1.1
Accept: application/json               //将返回json格式数据

?以上三种方式分析:

?

?? 1、使用参数

???? 现在很多open API是使用这种方式,但可能由于要编写的字符较多。

??? 淘宝的开放平台就是使用的此种方式



?

2、使用扩展名称

?? 丧失了同一url多种展现的方式,但现在这种在实际环境中是使用比较方便的。

3、使用Request Header中Accpet

?? 这种方式是最理想的,但如果你的资源要给用户直接通过浏览器访问(即html展现),那么由于浏览器的差异,发送上来的Accept Header头将是不一样的.?将导致服务器不知要返回什么格式的数据给你. 下面是浏览器的Accept Header:

Chrome:



?

Firefox:



?

IE9:



?我们使用第一种方式和第二种方式,在Spring中如何让配置

?

二、SpringMVC配置

?? 现spring完成内容协商(content negotiation)的工作是由ContentNegotiatingViewResolver来完成的。

它的工作模式支持我上面讲的三种,ContentNegotiatingViewResolver是根据客户提交的MimeType(如 text/html,application/xml)来跟服务端的一组viewResover的MimeType相比较,如果符合,即返回viewResover的数据。
而 /userController/getUser.xml, ContentNegotiatingViewResolver会首先将 .xml 根据mediaTypes属性将其转换成 application/xml,然后完成前面所说的比较。

?

1、我们看下ContentNegotiatingViewResolver的配置:

<!-- 根据客户端的不同的请求决定不同的view进行响应, 如 /user/getUser.json /user/getUser.xml -->
	<bean
		class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
		<!-- 设置为true以忽略对Accept Header的支持 -->
		<property name="ignoreAcceptHeader" value="true" />
		<!-- 在没有扩展名时即: "/user/getUser" 时的默认展现形式 -->
		<property name="defaultContentType" value="text/html" />

		<!-- 扩展名至mimeType的映射,即 /getUser.json => application/json -->
		<property name="mediaTypes">
			<map>
				<entry key="json" value="application/json" />
				<entry key="xml" value="application/xml" />
			</map>
		</property>
		<!-- 用于开启 /user/getUser?format=json 的支持 -->
		<property name="favorParameter" value="false" />
		<property name="viewResolvers">
			<list>
				<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
				<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
					<property name="viewClass"
						value="org.springframework.web.servlet.view.JstlView" />
					<property name="prefix" value="/WEB-INF/page/" />
					<property name="suffix" value=".jsp"></property>
				</bean>
			</list>
		</property>
		<property name="defaultViews">
			<list>
				<!-- for application/json -->
				<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
				<!-- for application/xml -->
				<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
					<property name="marshaller">
						<!-- xstream.XStreamMarshaller -->
						<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
							<property name