HttpMessageConverter和ContentNegotiatingViewResolver
2016-09-24 10:45
337 查看
HttpMessageConverter
在SpringMVC中,可以使用@RequestBody和@ResponseBody两个注解,分别完成请求报文到对象和对象到响应报文的转换,HttpMessageConverter完成了这种消息转换机制。HttpMessageConverte接口定义:
package org.springframework.http.converter; import java.io.IOException; import java.util.List; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; public interface HttpMessageConverter<T> { boolean canRead(Class<?> clazz, MediaType mediaType); boolean canWrite(Class<?> clazz, MediaType mediaType); List<MediaType> getSupportedMediaTypes(); T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; }
HttpMessageConverter接口的定义出现了成对的canRead(),read()和canWrite(),write()方法,MediaType是对请求的Media Type属性的封装。举个例子,当我们声明了下面这个处理方法。
@RequestMapping(value="/string", method=RequestMethod.POST) public @ResponseBody String readString(@RequestBody String string) { return "Read string '" + string + "'"; }
在SpringMVC进入readString方法前,会根据@RequestBody注解选择适当的HttpMessageConverter实现类来将请求参数解析到String变量中,具体来说是使用了StringHttpMessageConverter类,它的canRead()方法返回true,然后它的read()方法会从请求中读出请求参数,绑定到readString()方法的string变量中。
当SpringMVC执行readString方法后,由于返回值标识了@ResponseBody,SpringMVC将使用StringHttpMessageConverter的write()方法,将结果作为String值写入响应报文,当然,此时canWrite()方法返回true。
将上述过程集中描述的一个类是org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor,这个类同时实现了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler两个接口。前者是将请求报文绑定到处理方法形参的策略接口,后者则是对处理方法返回值进行处理的策略接口。RequestResponseBodyMethodProcessor这个类,同时充当了方法参数解析和返回值处理两种角色。而在此过程中,以是否有@RequestBody和@ResponseBody为条件,然后分别调用HttpMessageConverter来进行消息的读写。
ContentNegotiatingViewResolver
主要完成同一资源,多种展现的功能。三种指定资源格式的方式
Http Request Header: AcceptGET /test/123 HTTP/1.1 Accept: application/json //返回json格式数据 GET /test/123 HTTP/1.1 Accept: application/xml //返回xml格式数据
如果你的资源是通过浏览器访问的,那么由于浏览器的差异,传递到服务器的Accept Header是有差异的,将导致服务器不知道返回何种格式的数据给浏览器。下面是各种浏览器的Accept Header:
chrome: Accept:application/xml,application/xhtml+xml,textml;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 firefox: Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 IE8: Accept:image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
使用扩展名
/test/123.xml //返回xml格式数据 /test/123.json //返回json格式数据
丧失了同一url多种展现的方式,但现在这种在实际环境中是使用最多的,因为更加符合程序员的审美观。
使用参数
/test/123?format=json //返回json格式数据 /test/123?format=xml //返回xml格式数据
现在很多open API是使用这种方式,但可能由于要编写的字符较多,所以较少使用。
ContentNegotiatingViewResolver配置
内容协商(content negotiation)的工作是由ContentNegotiatingViewResolver来完成的。它的工作模式支持我上面讲的三种,ContentNegotiatingViewResolver是根据客户提交的MimeType(如 text/html,application/xml)来跟服务端的一组viewResover的MimeType相比较,如果符合,即返回viewResover的数据。ContentNegotiatingViewResolver配置:
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="true" /> <property name="favorParameter" value="true" /> <property name="parameterName" value="format" /> <property name="ignoreAcceptHeader" value="false" /> <property name="mediaTypes"> <value> json=application/json xml=application/xml </value> </property> <property name="defaultContentType" value="text/html" /> </bean> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="contentNegotiationManager" ref="contentNegotiationManager"/> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </list> </property> <property name="defaultViews"> <list> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> </list> </property> </bean>
相关文章推荐
- ContentNegotiatingViewResolver vs. HttpMessageConverter+ResponseBody Annotation
- Spring MVC 之 ContentNegotiatingViewResolver-02_(ajax+json格式的输入和输出)
- 转载Spring 3 MVC ContentNegotiatingViewResolver
- 解析mediaTypes+viewResolvers+viewResolvers+ContentNegotiatingViewResolver
- ContentNegotiatingViewResolver - 内容协商视图解析器
- Spring 3 MVC ContentNegotiatingViewResolver example
- org.springframework.web.servlet.view.ContentNegotiatingViewResolver 配置
- 7 ContentNegotiatingViewResolver
- SpringMVC大坑一枚:ContentNegotiatingViewResolver可能不利于SEO
- 8. Spring MVC4.1-ContentNegotiatingViewResolver
- Spring MVC-ContentNegotiatingViewResolver
- Spring mvc 视图解析器 ContentNegotiatingViewResolver 源码分析
- Spring mvc 视图解析器 ContentNegotiatingViewResolver 源码分析
- spring mvc ContentNegotiatingViewResolver 根据路径后缀,选择不同视图
- Spring 3 MVC ContentNegotiatingViewResolver Example
- ContentNegotiatingViewResolver spring REST中的内容协商(同一资源,多种展现:xml,json,html)
- SpringMVC大坑一枚:ContentNegotiatingViewResolver可能不利于SEO
- Spring MVC-ContentNegotiatingViewResolver 多视图返回
- ContentNegotiatingViewResolver
- 混合视图技术--ContentNegotiatingViewResolver