内容协商器(ContentNegotiatingViewResolver与contentNegotiationManager)是根据客户端的请求配置,响应不同格式的数据,这非常符合RESTful规范。
常见的配置
随着现在前后端分离的项目越来越多,Controller层现在通常返回JSON格式的数据,通用使用jackson或fastjson。在Controller的返回值上添加@ResponseBody,再配置对JSON格式的数据转换器即可,常用配置如下
message-converters
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="stringHttpMessageConverter"/>
<!-- jackson -->
<ref bean="jacksonHttpMessageConverter"/>
<!-- fastjson -->
<!-- <ref bean="fastJsonHttpMessageConverter"/> -->
</mvc:message-converters>
</mvc:annotation-driven>
字符串的消息转换
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<!-- 避免出现乱码 -->
<constructor-arg value="UTF-8" index="0"/>
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
使用jackson配置,参见:SpringMVC-Jackson
<!-- 使用jackson处理JSON的MessageConverter -->
<bean id="jacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<!-- 自定义Jackson的objectMapper -->
<property name="objectMapper" ref="customObjectMapper"/>
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 对jackson的配置 -->
<bean id="customObjectMapper" class="com.zmx.config.CustomObjectMapper"/>
使用fastJson配置,参见:SpringMVC集成fastjson
<bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<!-- 避免IE出现下载JSON文件的情况 -->
<value>text/html;charset=UTF-8</value>
</list>
</property>
<property name="fastJsonConfig" ref="fastJsonConfig"></property>
</bean>
<!-- fastJson的配置 -->
<bean id="fastJsonConfig" class="com.alibaba.fastjson.support.config.FastJsonConfig">
<property name="serializerFeatures">
<list>
<value>DisableCircularReferenceDetect</value>
<value>SortField</value>
</list>
</property>
<property name="charset" value="UTF-8"></property>
<property name="dateFormat" value="yyyy-MM-dd HH:mm:ss"></property>
</bean>
以上配置可以配合@ResponseBody用来响应JSON格式数据
内容协商器配置
contentNegotiationManager
就是同一资源,可以有多种表现形式,比如xml、json等,具体使用哪种表现形式,是可以协商的。这是RESTfull的一个重要特性,Spring Web MVC也支持这个功能。至于如何决定采用何种方式(视图)来展示内容呢,是根据客户端的参数决定?
- 后缀(xx/a.json返回JSON,xx/a.xml返回xml)
- request参数识别(xx/a?format=json,xx/a?format=xml)
- parameterName参数(xx/a?mediaType=json,xx/a?mediaType=xml)
- http请求头accept参数(Accept: application/xml 将返回xml格式数据,Accept: application/json 将返回json格式数据)RESTful规范
<!-- 配置使用内容协商器 -->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- favorPathExtension参数表示是否开启后缀,默认true。(使用形如/xx/a.json、/xx/a.xml的方式)-->
<property name="favorPathExtension" value="true"/>
<!-- favorParameter参数表示是否开启request参数识别,默认false。(使用形如/xx/a?format=json、/xx/a?format=xml的方式) -->
<property name="favorParameter" value="true"/>
<!-- parameterName参数表示使用参数的名字,默认format,如果配置为mediaType,则请求格式变为/xx/a?mediaType=json -->
<property name="parameterName" value="mediaType"/>
<!-- ignoreAcceptHeader表示是否关闭accept头识别,默认false,即默认开启accept头识别。-->
<property name="ignoreAcceptHeader" value="true"/>
<!-- defaultContentType表示服务器默认的MediaType类型,不指定默认返回html页面 -->
<property name="defaultContentType" value="text/html"/>
<!-- mediaTypes里的entry中的key做为文件名/URL后缀/参数,其内容类型就是entry对应的value值。-->
<property name="mediaTypes">
<map>
<entry key="json" value="application/json"/>
<entry key="xml" value="application/xml"/>
</map>
</property>
</bean>
defaultContentType根据实际情况来,如果前后端分离的项目,可以配置成“application/json”,如果不是前后端分离,可以配置text/html,否则页面的url都要加入资源类型的标识信息(用后缀、request参数识别等等)太繁琐
ContentNegotiatingViewResolver
<!-- 内容协商视图解析器,根据contentNegotiationManager使用的不同mediaTypes决定不同的view进行响应 默认使用json-->
<bean id="contentNegotiatingViewResolver"
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="0"/>
<!-- 内容协商管理器, 如已配置过管理器,这里可以不配置 -->
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
</bean>
html或jsp的视图
<!-- 返回资源型(html,jsp)的视图 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
JSON的视图
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
XML的视图
<bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="marshallerProperties">
<map>
<entry key="jaxb.encoding" value="UTF-8"></entry>
<!-- 放置xml自动缩进属性 -->
<entry key="jaxb.formatted.output" value="true"></entry>
</map>
</property>
<property name="packagesToScan" value="com.zmx.model"/>
<!--<property name="classesToBeBound">-->
<!--<list>-->
<!--<value>com.zmx.model.vo.EmployeeVo</value>-->
<!--</list>-->
<!--</property>-->
</bean>
</constructor-arg>
</bean>
Controller处理
@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
@ResponseBody
public EmployeeVo getEmployeeVo(@PathVariable("id") Long argId) {
EmployeeVo result = new EmployeeVo();
result.setId(argId);
result.setName("test");
result.setTelephone("021-10086");
result.setSex(new Short("0"));
result.setSalary(new BigDecimal(20356));
result.setIsOfficial(true);
result.setHobby("测试信息");
result.setBirthday(new DateTime().minusYears(20).toDate());
return result;
}
@RequestMapping(value = "/employee/{id}/info", method = RequestMethod.GET)
public String getEmployeJSP(@PathVariable("id") Long argId, Model model) {
model.addAttribute("username","test");
return "emp/info";
}
以上配置就可以处理:
http://localhost:8080/employee/123.json 返回JSON数据
http://localhost:8080/employee/123.xml 返回xml数据
http://localhost:8080/employee/123/info 或 http://localhost:8080/employee/123/info.html 返回页面
网友评论