@ResponseBody 和 RequestBody tx advice 和注解区别的区别

随笔- 348&
&&&&&&&&&&&&&
@RequestBody
&&& & i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
&&& & ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
&&& application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
&&& multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
&&& 其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
B) PUT方式提交时, 根据request header Content-Type的值来判断:
&&& application/x-www-form-urlencoded, 必须;
&&& multipart/form-data, 不能处理;
&&& 其他格式, 必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;
@ResponseBody
& & & 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
&&&&& 返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
HttpMessageConverter(HTTP消息转化器)
&*&Strategy&interface&that&specifies&a&converter&that&can&convert&from&and&to&HTTP&requests&and&responses.&&
&*&@author&Arjen&Poutsma&&
&*&@author&Juergen&Hoeller&&
&*&@since&3.0&&
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,&HttpMessageNotReadableE&&
&&&&void&write(T&t,&MediaType&contentType,&HttpOutputMessage&outputMessage)&&
&&&&&&&&&&&&throws&IOException,&HttpMessageNotWritableE&&
该接口定义了四个方法,分别是读取数据时的 canRead(), read() 和 写入数据时的canWrite(), write()方法。
在使用 &mvc:annotation-driven /&标签配置时,默认配置了RequestMappingHandlerAdapter(注意是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,详情查看Spring 3.1 document &16.14&Configuring Spring MVC&章节),并为他配置了一下默认的HttpMessageConverter:
ByteArrayHttpMessageConverter&converts&byte&arrays.&&
&&&&StringHttpMessageConverter&converts&strings.&&
&&&&ResourceHttpMessageConverter&converts&to/from&org.springframework.core.io.Resource&for&all&media&types.&&
&&&&SourceHttpMessageConverter&converts&to/from&a&javax.xml.transform.Source.&&
&&&&FormHttpMessageConverter&converts&form&data&to/from&a&MultiValueMap&String,&String&.&&
&&&&Jaxb2RootElementHttpMessageConverter&converts&Java&objects&to/from&XML&&&added&if&JAXB2&is&present&on&the&classpath.&&
&&&&MappingJacksonHttpMessageConverter&converts&to/from&JSON&&&added&if&Jackson&is&present&on&the&classpath.&&
&&&&AtomFeedHttpMessageConverter&converts&Atom&feeds&&&added&if&Rome&is&present&on&the&classpath.&&
&&&&RssChannelHttpMessageConverter&converts&RSS&feeds&&&added&if&Rome&is&present&on&the&classpath.&&
ByteArrayHttpMessageConverter:&负责读取二进制格式的数据和写出二进制格式的数据;&&
StringHttpMessageConverter:&&&负责读取字符串格式的数据和写出二进制格式的数据;&&
ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据;&&&
FormHttpMessageConverter:&&&&&&&负责读取form提交的数据(能读取的数据格式为&application/x-www-form-urlencoded,不能读取multipart/form-data格式数据);负责写入application/x-www-from-urlencoded和multipart/form-data格式的数据;&&
MappingJacksonHttpMessageConverter:&&负责读取和写入json格式的数据;&&
SouceHttpMessageConverter:&&&&&&&&&&&&&&&&&&&负责读取和写入&xml&中javax.xml.transform.Source定义的数据;&&
Jaxb2RootElementHttpMessageConverter:&&负责读取和写入xml&标签格式的数据;&&
AtomFeedHttpMessageConverter:&&&&&&&&&&&&&&负责读取和写入Atom格式的数据;&&
RssChannelHttpMessageConverter:&&&&&&&&&&&负责读取和写入RSS格式的数据;&&
当使用@RequestBody和@ResponseBody注解时,RequestMappingHandlerAdapter就使用它们来进行读取或者写入相应格式的数据&&
HttpMessageConverter匹配过程:
@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据;
spring 3.1源代码如下:
private&Object&readWithMessageConverters(MethodParameter&methodParam,&HttpInputMessage&inputMessage,&Class&paramType)&&
&&&&&&&&&&&&throws&Exception&{&&
&&&&&&&&MediaType&contentType&=&inputMessage.getHeaders().getContentType();&&
&&&&&&&&if&(contentType&==&null)&{&&
&&&&&&&&&&&&StringBuilder&builder&=&new&StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));&&
&&&&&&&&&&&&String&paramName&=&methodParam.getParameterName();&&
&&&&&&&&&&&&if&(paramName&!=&null)&{&&
&&&&&&&&&&&&&&&&builder.append('&');&&
&&&&&&&&&&&&&&&&builder.append(paramName);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&throw&new&HttpMediaTypeNotSupportedException(&&
&&&&&&&&&&&&&&&&&&&&"Cannot&extract&parameter&("&+&builder.toString()&+&"):&no&Content-Type&found");&&
&&&&&&&&}&&
&&&&&&&&List&MediaType&&allSupportedMediaTypes&=&new&ArrayList&MediaType&();&&
&&&&&&&&if&(this.messageConverters&!=&null)&{&&
&&&&&&&&&&&&for&(HttpMessageConverter&?&&messageConverter&:&this.messageConverters)&{&&
&&&&&&&&&&&&&&&&allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());&&
&&&&&&&&&&&&&&&&if&(messageConverter.canRead(paramType,&contentType))&{&&
&&&&&&&&&&&&&&&&&&&&if&(logger.isDebugEnabled())&{&&
&&&&&&&&&&&&&&&&&&&&&&&&logger.debug("Reading&["&+&paramType.getName()&+&"]&as&\""&+&contentType&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&+"\"&using&["&+&messageConverter&+&"]");&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&return&messageConverter.read(paramType,&inputMessage);&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&throw&new&HttpMediaTypeNotSupportedException(contentType,&allSupportedMediaTypes);&&
@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的HttpMessageConverter;
源代码如下:
private&void&writeWithMessageConverters(Object&returnValue,&&
&&&&&&&&&&&&&&&&HttpInputMessage&inputMessage,&HttpOutputMessage&outputMessage)&&
&&&&&&&&&&&&&&&&throws&IOException,&HttpMediaTypeNotAcceptableException&{&&
&&&&&&&&&&&&List&MediaType&&acceptedMediaTypes&=&inputMessage.getHeaders().getAccept();&&
&&&&&&&&&&&&if&(acceptedMediaTypes.isEmpty())&{&&
&&&&&&&&&&&&&&&&acceptedMediaTypes&=&Collections.singletonList(MediaType.ALL);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&MediaType.sortByQualityValue(acceptedMediaTypes);&&
&&&&&&&&&&&&Class&?&&returnValueType&=&returnValue.getClass();&&
&&&&&&&&&&&&List&MediaType&&allSupportedMediaTypes&=&new&ArrayList&MediaType&();&&
&&&&&&&&&&&&if&(getMessageConverters()&!=&null)&{&&
&&&&&&&&&&&&&&&&for&(MediaType&acceptedMediaType&:&acceptedMediaTypes)&{&&
&&&&&&&&&&&&&&&&&&&&for&(HttpMessageConverter&messageConverter&:&getMessageConverters())&{&&
&&&&&&&&&&&&&&&&&&&&&&&&if&(messageConverter.canWrite(returnValueType,&acceptedMediaType))&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&messageConverter.write(returnValue,&acceptedMediaType,&outputMessage);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(logger.isDebugEnabled())&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&MediaType&contentType&=&outputMessage.getHeaders().getContentType();&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(contentType&==&null)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&contentType&=&acceptedMediaT&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&logger.debug("Written&["&+&returnValue&+&"]&as&\""&+&contentType&+&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"\"&using&["&+&messageConverter&+&"]");&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&this.responseArgumentUsed&=&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&for&(HttpMessageConverter&messageConverter&:&messageConverters)&{&&
&&&&&&&&&&&&&&&&&&&&allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&throw&new&HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);&&
&&&&&&&&}&&
MappingJacksonHttpMessageConverter 调用了 objectMapper.writeValue(OutputStream stream, Object)方法,使用@ResponseBody注解返回的对象就传入Object参数内。若返回的对象为已经格式化好的json串时,不使用@RequestBody注解,而应该这样处理:
1、response.setContentType("application/ charset=UTF-8");
2、response.getWriter().print(jsonStr);
直接输出到body区,然后的视图为void。
参考资料:
1、 Spring 3.1 Doc:&
spring-3.1.0/docs/spring-framework-reference/html/mvc.html
2、Spring 3.x MVC 入门4 -- @ResponseBody & @RequestBody
转载地址:/qq/p/3760651.html
ok 上面讲解了实现的过程,简单的可以理解为只要有对应协议的解析器,你就可以通过几行配置,几个注解完成协议&&对象的转换工作。注意:Spring默认的json协议解析由Jackson完成,所以要添加jackson.jar包。
使用@ResponseBody& 带来的好处就是由spring 将协议转化为对象,不用我们自己再去转化 同样@RequestBody也是,比如我们在前台传递了参数而controller中使用@RequestBody 则可以直接获得pojo对象,不用我们再去获取参数,组装对象。
下面看看小demo
1、前端代码post提交:
[javascript]&&
function&profilep()&{&&
&&&&&&&&var&mydata&=&'{"name":"'&+&$('#name').val()&+&'","id":"'&&
&&&&&&&&&&&&&&&&+&$('#id').val()&+&'","password":"'&+&$('#password').val()&&
&&&&&&&&&&&&&&&&+&'"}';&&
&&&&&&&&$.ajaxSetup({&&
&&&&&&&&&&&&contentType&:&'application/json'&&
&&&&&&&&});&&&
&&&&&&&&$.post('http://localhost:18080/website2/user/save2.do',&mydata,&&
&&&&&&&&&&&&&&&&function(data)&{&&
&&&&&&&&&&&&&&&&&&&&alert("id:&"&+&data.id&+&"\nname:&"&+&data.name&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&+&"\password:&"&+&data.password);&&
&&&&&&&&&&&&&&&&},&'json');&&
2、后台代码:
@ResponseBody&&
@RequestMapping(value&=&"/save2.do"&&,method&=&RequestMethod.POST)&&
public&User&info2(@RequestBody&User&user)&{&&
&&&&String&id&=&user.getId();&&
&&&&String&name&=&user.getName();&&
&&&&String&password&=&user.getPassword();&&
&&&&Map&String,&String&&map&=&new&HashMap&String,&String&();&&
&&&&map.put("id",&id);&&
&&&&map.put("name",&name);&&
&&&&map.put("password",&password);&&
&&&&userService.saveUser(map);&&
&&&&User&user2=&new&User(id,name,password);&&
&&&&return&user2;&&
3、上面两个都是post方法其实get方法也是一样的:
前端代码:
[javascript]&&
function&profile()&{&&
&&&&var&url&=&'http://localhost:18080/website2/user/save.do?';&&
&&&&var&query&=&'id='&+&$('#id').val()&+&'&name='&+&$('#name').val()&&
&&&&&&&&&&&&+&'&password='&+&$('#password').val();&&
&&&&url&+=&&&
&&&&$.get(url,&function(data)&{&&
&&&&&&&&alert("id:&"&+&data.id&+&"\nname:&"&+&data.name&+&"\nstatus:&"&&
&&&&&&&&&&&&&&&&+&data.password);&&
后台代码:
@ResponseBody&&
@RequestMapping(value&=&"/save.do"&&,method&=&RequestMethod.GET)&&
public&User&info(HttpServletRequest&request)&{&&
&&&&String&id&=&request.getParameter("id");&&
&&&&String&name&=&request.getParameter("name");&&
&&&&String&password&=&request.getParameter("password");&&
&&&&Map&String,&String&&map&=&new&HashMap&String,&String&();&&
&&&&map.put("id",&id);&&
&&&&map.put("name",&name);&&
&&&&map.put("password",&password);&&
&&&&userService.saveUser(map);&&
&&&&User&user=&new&User(id,name,password);&&
&&&&return&&&
上面的$.get方法是使用GET方式进行异步请求。$.post方法使用POST方式来进行异步请求。
$.get 、$.post 方法的格式相同,这里就以$.get为列:
$.get(url [, data] [, callback] [, type])
url:请求的HTML页的URL地址
data(可选):发送至服务器的key/value数据会未为QueryString附加到请求URL中
callback(可选):载入成功时回调函数(即当Response的返回状态为success才调用)自动将请求结果和状态传递给该方法
type(可选):服务器端返回内容的格式,包括xml,html,script,json,text和_default.
这个格式通过上面的post方法和get方法可以看到,像post的那个方法就比较完整!
&posted on
阅读(...) 评论()spring配置注解同时启用@ResponseBody,@RequestBody 注解实现实体与json转换 - CSDN博客
spring配置注解同时启用@ResponseBody,@RequestBody 注解实现实体与json转换
&?xml&version=&1.0&&encoding=&UTF-8&?&
&beans&xmlns=&http://www.springframework.org/schema/beans&
xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&
xmlns:context=&http://www.springframework.org/schema/context&
xmlns:mvc=&http://www.springframework.org/schema/mvc&
xsi:schemaLocation=&http:
&!--&注解扫描包&--&
&context:component-scan&base-package=&com.key&&/&
&!--&AOP式方法级权限检查&--&
class=&org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator&
depends-on=&lifecycleBeanPostProcessor&&
&property&name=&proxyTargetClass&&value=&true&/&
&!--&开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行&--&&&&&&&&&&&&&&&&
&bean&class=&org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor&&&
&property&name=&securityManager&&ref=&securityManager&/&&
&!--&静态资源(js/image/css)的访问&--&
&mvc:resources&location=&/&&mapping=&/*/**&/&&
&!--&定义视图解析器&--&
&bean&id=&viewResolver&&class=&org.springframework.web.servlet.view.InternalResourceViewResolver&&
&property&name=&prefix&&value=&/&&&/property&
&property&name=&suffix&&value=&.jsp&&&/property&
&!--&注解@RequestBody接收json同时转化为实体的配置&--&
&&bean&id=&mappingJacksonHttpMessageConverter&&&
&&&&&&&&class=&org.springframework.http.converter.json.MappingJacksonHttpMessageConverter&&&
&property&name=&objectMapper&&
&bean&class=&org.codehaus.jackson.map.ObjectMapper&&
&property&name=&dateFormat&&
&bean&class=&java.text.SimpleDateFormat&&
&constructor-arg&type=&java.lang.String&&value=&yyyy-MM-dd&HH:mm:ss&&&/constructor-arg&
&/property&
&/property&&
&&&&&&&&/bean&
&bean&class=&org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter&&&&
&&&&&&&&&property&name=&messageConverters&&&&
&&&&&&&&&&&&&list&&&
&&&&&&&&&&&&&&&&&ref&bean=&mappingJacksonHttpMessageConverter&&/&&&
&&&&&&&&&&&&&/list&&&
&&&&&&&&&/property&&&
&&&&&/bean&&&
&&&/beans&
本文已收录于以下专栏:
相关文章推荐
上一篇分析了spring中是如何通过使用@ResponseBody注解,实现自动转换Java对象为XML,JSON数据到Reponse中。
接下来看看如果request中包含了XML或者JSON...
配合@ResponseBody注解,以及HTTP Request Header中的Accept属性,Controller返回的Java对象可以自动被转换成对应的XML或者JSON数据。
配合@RequestBody注解,以及HTTP Request Header中的Content-Type属性,HTTP Request Body中包含的XML或者JSON数据可以自动被转换成对应的Ja...
Spring3.1开始使用新的HandlerMapping 和 HandlerAdapter 来支持@Contoller 和@RequestMapping注解处理:处理器映射RequestMappin...
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服!
相关参考:
Spring 注解...
SpringMVC层跟JSon结合,几乎不需要做什么配置,代码实现也相当简洁。再也不用为了组装协议而劳烦辛苦了!
一、Spring注解@ResponseBody,@RequestBody和H...
/blog/1628861
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,Sprin...
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服!
相关参考:
Spring 注解...
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服!
相关参考:
Spring 注解...
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服!
相关参考:
Spring 注解...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)@RequestBody, @ResponseBody 注解详解(转)
来源:博客园

@responsebody表示该方法的返回结果直接写入HTTP response body中一般在异
步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路
径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
引言: 
接上一篇文章讲述处理@RequestMapping的方法参数绑定之后,详细介绍下@RequestBody、@ResponseBody的具体用法和使用时机;同时对曾经看的一篇文章中讲述的某些部分进行澄清 (文章地址:)。
 
简介:
@RequestBody
作用: 
i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
 
B) PUT方式提交时, 根据request header Content-Type的值来判断:
 
application/x-www-form-urlencoded, 必须;
multipart/form-data, 不能处理;
其他格式, 必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;
 
 
@ResponseBody
 
作用: 
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
 
 
 
HttpMessageConverter


&span style="font-family:Microsoft YaH"&/**
 * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @since 3.0
 */
public interface HttpMessageConverter&T& {

* Indicates whether the given class can be read by this converter.
* @param clazz the class to test for readability
* @param mediaType the media type to read, can be {@code null} if not specified.
* Typically the value of a {@code Content-Type} header.
* @return {@code true} {@code false} otherwise
boolean canRead(Class&?& clazz, MediaType mediaType);

* Indicates whether the given class can be written by this converter.
* @param clazz the class to test for writability
* @param mediaType the media type to write, can be {@code null} if not specified.
* Typically the value of an {@code Accept} header.
* @return {@code true} {@code false} otherwise
boolean canWrite(Class&?& clazz, MediaType mediaType);

* Return the list of {@link MediaType} objects supported by this converter.
* @return the list of supported media types
List&MediaType& getSupportedMediaTypes();

* Read an object of the given type form the given input message, and returns it.
* @param clazz the type of object to return. This type must have previously been passed to the
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
T read(Class&? extends T& clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableE

* Write an given object to the given output message.
* @param t the object to write to the output message. The type of this object must have previously been
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
* default content type of the converter must be used. If not {@code null}, this media type must have
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
* returned {@code true}.
* @param outputMessage the message to write to
* @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableE

}
&/span&


该接口定义了四个方法,分别是读取数据时的 canRead(), read() 和 写入数据时的canWrite(), write()方法。
 
在使用 &mvc:annotation-driven /&标签配置时,默认配置了RequestMappingHandlerAdapter(注意是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,详情查看Spring 3.1 document “16.14 Configuring Spring MVC”章节),并为他配置了一下默认的HttpMessageConverter:


ByteArrayHttpMessageConverter converts byte arrays.

StringHttpMessageConverter converts strings.

ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.

SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.

FormHttpMessageConverter converts form data to/from a MultiValueMap&String, String&.

Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML — added if JAXB2 is present on the classpath.

MappingJacksonHttpMessageConverter converts to/from JSON — added if Jackson is present on the classpath.

AtomFeedHttpMessageConverter converts Atom feeds — added if Rome is present on the classpath.

RssChannelHttpMessageConverter converts RSS feeds — added if Rome is present on the classpath.


ByteArrayHttpMessageConverter: 负责读取二进制格式的数据和写出二进制格式的数据;
StringHttpMessageConverter:
负责读取字符串格式的数据和写出二进制格式的数据;
 
ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据; 
FormHttpMessageConverter:
负责读取form提交的数据(能读取的数据格式为 
application/x-www-form-urlencoded,不能读取multipart/form-data格式数据);负责写入
application/x-www-from-urlencoded和multipart/form-data格式的数据;
 
MappingJacksonHttpMessageConverter:
负责读取和写入json格式的数据;
 
SouceHttpMessageConverter:
负责读取和写入 xml 中javax.xml.transform.Source定义的数据;
Jaxb2RootElementHttpMessageConverter:
负责读取和写入xml 标签格式的数据;
 
AtomFeedHttpMessageConverter:
负责读取和写入Atom格式的数据;
RssChannelHttpMessageConverter:
负责读取和写入RSS格式的数据;
 
当使用@RequestBody和@ResponseBody注解时,RequestMappingHandlerAdapter就使用它们来进行读取或者写入相应格式的数据。
 
HttpMessageConverter匹配过程:
@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据;
spring 3.1源代码如下:


private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType)
throws Exception {

MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
String paramName = methodParam.getParameterName();
if (paramName != null) {
builder.append(' ');
builder.append(paramName);
throw new HttpMediaTypeNotSupportedException(
"Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
}

List&MediaType& allSupportedMediaTypes = new ArrayList&MediaType&();
if (this.messageConverters != null) {
for (HttpMessageConverter&?& messageConverter : this.messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
if (messageConverter.canRead(paramType, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
+"\" using [" + messageConverter + "]");
return messageConverter.read(paramType, inputMessage);
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
}


@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的HttpMessageConverter;
源代码如下:


private void writeWithMessageConverters(Object returnValue,
HttpInputMessage inputMessage, HttpOutputMessage outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException {
List&MediaType& acceptedMediaTypes = inputMessage.getHeaders().getAccept();
if (acceptedMediaTypes.isEmpty()) {
acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
MediaType.sortByQualityValue(acceptedMediaTypes);
Class&?& returnValueType = returnValue.getClass();
List&MediaType& allSupportedMediaTypes = new ArrayList&MediaType&();
if (getMessageConverters() != null) {
for (MediaType acceptedMediaType : acceptedMediaTypes) {
for (HttpMessageConverter messageConverter : getMessageConverters()) {
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
if (logger.isDebugEnabled()) {
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = acceptedMediaT
logger.debug("Written [" + returnValue + "] as \"" + contentType +
"\" using [" + messageConverter + "]");
this.responseArgumentUsed = true;
return;
for (HttpMessageConverter messageConverter : messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}



补充:
MappingJacksonHttpMessageConverter 调用了 objectMapper.writeValue(OutputStream stream, Object)方法,使用@ResponseBody注解返回的对象就传入Object参数内。若返回的对象为已经格式化好的json串时,不使用@RequestBody注解,而应该这样处理:
1、response.setContentType("application/ charset=UTF-8");
2、response.getWriter().print(jsonStr);
直接输出到body区,然后的视图为void。

 
参考资料:
 
1、 Spring 3.1 Doc: 
spring-3.1.0/docs/spring-framework-reference/html/mvc.html

2、Spring 3.x MVC 入门4 -- @ResponseBody & @RequestBody

@responsebody表示该方法的返回结果直接写入HTTP response body中一般在异
步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路
径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
引言: 
接上一篇文章讲述处理@RequestMapping的方法参数绑定之后,详细介绍下@RequestBody、@ResponseBody的具体用法和使用时机;同时对曾经看的一篇文章中讲述的某些部分进行澄清 (文章地址:)。
 
简介:
@RequestBody
作用: 
i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
 
B) PUT方式提交时, 根据request header Content-Type的值来判断:
 
application/x-www-form-urlencoded, 必须;
multipart/form-data, 不能处理;
其他格式, 必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;
 
 
@ResponseBody
 
作用: 
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
 
 
 
HttpMessageConverter


&span style="font-family:Microsoft YaH"&/**
 * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @since 3.0
 */
public interface HttpMessageConverter&T& {

* Indicates whether the given class can be read by this converter.
* @param clazz the class to test for readability
* @param mediaType the media type to read, can be {@code null} if not specified.
* Typically the value of a {@code Content-Type} header.
* @return {@code true} {@code false} otherwise
boolean canRead(Class&?& clazz, MediaType mediaType);

* Indicates whether the given class can be written by this converter.
* @param clazz the class to test for writability
* @param mediaType the media type to write, can be {@code null} if not specified.
* Typically the value of an {@code Accept} header.
* @return {@code true} {@code false} otherwise
boolean canWrite(Class&?& clazz, MediaType mediaType);

* Return the list of {@link MediaType} objects supported by this converter.
* @return the list of supported media types
List&MediaType& getSupportedMediaTypes();

* Read an object of the given type form the given input message, and returns it.
* @param clazz the type of object to return. This type must have previously been passed to the
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
T read(Class&? extends T& clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableE

* Write an given object to the given output message.
* @param t the object to write to the output message. The type of this object must have previously been
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
* default content type of the converter must be used. If not {@code null}, this media type must have
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
* returned {@code true}.
* @param outputMessage the message to write to
* @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableE

}
&/span&


该接口定义了四个方法,分别是读取数据时的 canRead(), read() 和 写入数据时的canWrite(), write()方法。
 
在使用 &mvc:annotation-driven /&标签配置时,默认配置了RequestMappingHandlerAdapter(注意是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,详情查看Spring 3.1 document “16.14 Configuring Spring MVC”章节),并为他配置了一下默认的HttpMessageConverter:


ByteArrayHttpMessageConverter converts byte arrays.

StringHttpMessageConverter converts strings.

ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.

SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.

FormHttpMessageConverter converts form data to/from a MultiValueMap&String, String&.

Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML — added if JAXB2 is present on the classpath.

MappingJacksonHttpMessageConverter converts to/from JSON — added if Jackson is present on the classpath.

AtomFeedHttpMessageConverter converts Atom feeds — added if Rome is present on the classpath.

RssChannelHttpMessageConverter converts RSS feeds — added if Rome is present on the classpath.


ByteArrayHttpMessageConverter: 负责读取二进制格式的数据和写出二进制格式的数据;
StringHttpMessageConverter:
负责读取字符串格式的数据和写出二进制格式的数据;
 
ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据; 
FormHttpMessageConverter:
负责读取form提交的数据(能读取的数据格式为 
application/x-www-form-urlencoded,不能读取multipart/form-data格式数据);负责写入
application/x-www-from-urlencoded和multipart/form-data格式的数据;
 
MappingJacksonHttpMessageConverter:
负责读取和写入json格式的数据;
 
SouceHttpMessageConverter:
负责读取和写入 xml 中javax.xml.transform.Source定义的数据;
Jaxb2RootElementHttpMessageConverter:
负责读取和写入xml 标签格式的数据;
 
AtomFeedHttpMessageConverter:
负责读取和写入Atom格式的数据;
RssChannelHttpMessageConverter:
负责读取和写入RSS格式的数据;
 
当使用@RequestBody和@ResponseBody注解时,RequestMappingHandlerAdapter就使用它们来进行读取或者写入相应格式的数据。
 
HttpMessageConverter匹配过程:
@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据;
spring 3.1源代码如下:


private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType)
throws Exception {

MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
String paramName = methodParam.getParameterName();
if (paramName != null) {
builder.append(' ');
builder.append(paramName);
throw new HttpMediaTypeNotSupportedException(
"Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
}

List&MediaType& allSupportedMediaTypes = new ArrayList&MediaType&();
if (this.messageConverters != null) {
for (HttpMessageConverter&?& messageConverter : this.messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
if (messageConverter.canRead(paramType, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
+"\" using [" + messageConverter + "]");
return messageConverter.read(paramType, inputMessage);
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
}


@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的HttpMessageConverter;
源代码如下:


private void writeWithMessageConverters(Object returnValue,
HttpInputMessage inputMessage, HttpOutputMessage outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException {
List&MediaType& acceptedMediaTypes = inputMessage.getHeaders().getAccept();
if (acceptedMediaTypes.isEmpty()) {
acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
MediaType.sortByQualityValue(acceptedMediaTypes);
Class&?& returnValueType = returnValue.getClass();
List&MediaType& allSupportedMediaTypes = new ArrayList&MediaType&();
if (getMessageConverters() != null) {
for (MediaType acceptedMediaType : acceptedMediaTypes) {
for (HttpMessageConverter messageConverter : getMessageConverters()) {
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
if (logger.isDebugEnabled()) {
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = acceptedMediaT
logger.debug("Written [" + returnValue + "] as \"" + contentType +
"\" using [" + messageConverter + "]");
this.responseArgumentUsed = true;
return;
for (HttpMessageConverter messageConverter : messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}



补充:
MappingJacksonHttpMessageConverter 调用了 objectMapper.writeValue(OutputStream stream, Object)方法,使用@ResponseBody注解返回的对象就传入Object参数内。若返回的对象为已经格式化好的json串时,不使用@RequestBody注解,而应该这样处理:
1、response.setContentType("application/ charset=UTF-8");
2、response.getWriter().print(jsonStr);
直接输出到body区,然后的视图为void。

 
参考资料:
 
1、 Spring 3.1 Doc: 
spring-3.1.0/docs/spring-framework-reference/html/mvc.html

2、Spring 3.x MVC 入门4 -- @ResponseBody & @RequestBody

免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动

我要回帖

更多关于 注解和注释的区别 的文章

 

随机推荐