什么是内容协商
简单点说,就是同一资源,可以有多种表现形式,比如xml、json等,具体使用哪种表现形式,是可以协商的。
这是RESTfull的一个重要特性,Spring Web MVC也支持这个功能。
Spring MVC REST是如何决定采用何种方式(视图)来展示内容呢?
一:根据Http请求的header中的Accept属性的值来判读,比如:
Accept: application/xml 将返回xml格式数据
Accept: application/json 将返回json格式数据
优点:是这种方式是理想的标准方式
缺点:是由于浏览器的差异,导致发送的Accept Header头可能会不一样,从而导致服务器不知要返回什么格式的数据
二:根据扩展名来判断,比如:
/mvc/test.xml 将返回xml格式数据
/mvc/test.json 将返回json格式数据
/mvc/test.html 将返回html格式数据
缺点:丧失了同一URL的多种展现方式。在实际环境中使用还是较多的,因为这种方式更符合程序员的习惯
三:根据参数来判断
/mvc/test?format=xml 将返回xml数据
/mvc/test?format=json 将返回json数据
缺点:需要额外的传递format参数,URL变得冗余繁琐,缺少了REST的简洁风范
使用内容协商的功能,如果不使用第三种方式的话,3.2的版本可以什么都不用配置,默认就能支持前面两种。下面还是看看怎么配置,示例如下:
需要在spring的配置文件中做配置,示例如下:
<!--1、检查扩展名(如my.pdf);2、检查Parameter(如my?format=pdf);3、检查Accept Header-->
<bean id= "contentNegotiationManager" class= "org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
<property name= "favorPathExtension" value= "true" />
<!-- 用于开启 /userinfo/123?format=json 的支持 -->
<property name= "favorParameter" value= "true" />
<property name= "parameterName" value= "format"/>
<!-- 是否忽略Accept Header -->
<property name= "ignoreAcceptHeader" value= "false"/>
<property name= "mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 -->
<value>
ccjson=application/json
ccxml=application/xml
html=text/html
</value>
</property>
<!-- 默认的content type -->
<property name= "defaultContentType" value= "text/html" />
</bean>
<!-- ========================= VIEW定义 ========================= -->
<!-- 内容协商视图解析器;根据客户端不同的请求决定不同的view进行响应 -->
<!-- 会自动根据解析的contentType来决定使用哪个视图解析器(默认使用整个web应用中的viewResolver) -->
<bean class= "org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order= "0">
<!-- 内容协商管理器 用于决定media type -->
<property name= "contentNegotiationManager" ref= "contentNegotiationManager"/>
<!-- 默认视图 放在解析链最后 -->
<property name= "defaultViews">
<list>
<bean class= "org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
<bean class= "org.springframework.web.servlet.view.xml.MarshallingView">
<property name= "marshaller">
<bean class= "org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name= "packagesToScan" value= "cn.javass"></property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
<!-- bean name view resolver-->
<bean class= "org.springframework.web.servlet.view.BeanNameViewResolver" p:order= "1"/>
<!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用 html)- -->
<bean id= "defaultViewResolver" 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/jsp/"/>
<property name= "suffix" value= ".jsp"/>
</bean>
在mvc:annotation-driven里面配置使用内容协商
<mvc:annotation-driven
validator= "validator"
conversion-service= "conversionService"
content-negotiation-manager= "contentNegotiationManager"
>
</mvc:annotation-driven>
测试文件的变化:
1:dataType: ‘json’, 这句话可以注掉了
2:在请求的url上添加 后缀,还有参数试试看,注意,前面配置的映射格式是ccjson、ccxml哦,例如:
url:'/mvcexample/hello?format=ccxml',
url:'/mvcexample/hello?format=ccjson',
url:‘/mvcexample/hello.ccxml',
url:‘/mvcexample/hello.ccjson',
应该可以看到根据不同的请求,服务端回返回不同格式的数据。