注解responsestatus 注解body可以逆向吗

&&完spring mvc如何实现不使用@ResponseBody注解接收前端ajax请求?如题, 在controller中的一个方法 &是ajax请求的方法 &无返回值的方法&如果不加@ResponseBody 会提示 xxxx.jsp找不到, 只有加了@ResponseBody springmvc才会认为这是一个ajax请求 &而非需要跳转页面。 &有没有什么办法不使用这个注解在springmvc中还可以使用ajax(在无返回值的方法中)下面是视图解析配置:
&!-- freemarker 视图解析器 --&
&bean id=&freemarkerConfig& class=&org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer&&
&property name=&templateLoaderPath& value=&/WEB-INF/ftl/pages&/&
View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver.
&bean id=&viewResolver& class=&org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver&&
&property name=&cache& value=&true&/&
&property name=&prefix& value=&&/&
&property name=&suffix& value=&.ftl&/&
&property name=&contentType& value=&text/ charset=utf-8& /&
&!-- jsp视图解析器 --&
&bean class=&org.springframework.web.servlet.view.InternalResourceViewResolver&&
&property name=&prefix& value=&/WEB-INF/jsp/&/&
&property name=&suffix& value=&.jsp& /&
&/bean&5个牛币所有回答列表(5)&LV4有2种方式。1.在spring mvc的controller中设置http响应头content type类型为json格式response.setContentType(&application/charset=utf-8&)然后在response中输出json的字符串。此时的controller的方法可以不需要@ResponseBody注解返回json,可以是void2.在spring mvc的view层设置响应头content type类型为json格式,比如jsp中的语法&%@ page language=&java& contentType=&application/ charset=UTF-8& pageEncoding=&UTF-8&%&然后在view中输出json的字符串。其他view层技术大同小异,自己搜索下语法即可最佳答案可以通过获取response对象,然后使用response.write()方法输出,不懂追I问&LV2
//no cache
response.setHeader(&Cache-Control&, &no-cache&);
response.setHeader(&Expires&, &0&);
response.setHeader(&Pragma&, &No-cache&);
byte[] bytes = anyString.getBytes(encoding);
//fixed firefox3 未组织好的错误
response.setContentType(&text/plain&);
response.setContentType(&application/charset=utf-8&);
response.setContentLength(bytes.length);
response.getOutputStream().write(bytes);
catch (Exception e)
e.printStackTrace();
}&@RepsonseBody 是基于Ognl表达式的,那么你在前台就需要用 '.属性' 如'member.name'的方式来访问,这样造成代码不易维护,改动一点代码,可能造成很难维护的后果所以不用,简单的单体对象可以用return null等等等等等等等等等等等等最热搜索问答话题编程语言基础Web开发数据库开发客户端开发脚本工具游戏开发服务器软硬件开源组件类库相关问答等等等等等等等等完等完等最近浏览暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级暂无贡献等级扫描二维码关注最代码为好友"/>扫描二维码关注最代码为好友深入Spring:自定义ResponseBody - 简书
深入Spring:自定义ResponseBody
介绍了SpringMvc的RequestMappingHandlerMapping,自定义了Controller和RequestMapping。这里再介绍一下HandlerAdapter和HttpMessageConverter,并通过自定义注解来实现RequestBody和ResponseBody。HttpMessageConverter最常见的应用就是json的decode和encode。
RequestBody和ResponseBody
介绍了RequestMappingHandlerMapping在DispatcherServlet的作用。RequestMappingHandlerMapping扫描了RequestMapping注释的HttpRequest对应的处理方法,并通过实现HandlerMapping的接口代理对应的方法。而HandlerAdapter则是封装了HandlerMapping的方法,并围绕HandlerMapping实现一些嵌入操作。RequestMappingHandlerAdapter是其中一个典型的例子,这个类包含HandlerMethodArgumentResolver,HandlerMethodReturnValueHandler的一些实现类来处理RequestMapping的参数和返回值。
private HandlerMethodArgumentResolverComposite argumentR
private HandlerMethodReturnValueHandlerComposite returnValueH
RequestResponseBodyMethodProcessor是HandlerAdapter的内部一个重要的类,这个类同时实现了HandlerMethodArgumentResolver,HandlerMethodReturnValueHandler。其中HandlerMethodArgumentResolver接口有两个方法。
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws E
HandlerMethodReturnValueHandler接口同样也有两个方法。
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws E
所以从RequestResponseBodyMethodProcessor实现的方法,就可以看出来这个类,会处理被@RequestBody注解的参数,和@ResponseBody注解的返回值。
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class);
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotationUtils.findAnnotation(returnType.getContainingClass(), ResponseBody.class) != null ||
returnType.getMethodAnnotation(ResponseBody.class) != null);
接下来就介绍一下自定义ResponseBody和RequestBody的使用方法。
自定义ResponseBody和RequestBody
自定义注解,因为都是附加的注解,就不需要再加上@Component的注解了。@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyResponseBody {
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRequestBody {
定义数据结构,简便起见,这里只decode和encode特定的类。RequestData是@MyRequestBody修饰的类,ResponseData是@MyResponseBody修饰的类。 public static class RequestData {
private Map&String, String&
public Map&String, String& getData() {
public void setData(Map&String, String& data) {
this.data =
public String toString() {
return "{\"data\":" + data + "}";
public static class ResponseData {
private Map&String, String&
public Map&String, String& getData() {
public void setData(Map&String, String& data) {
this.data =
定义controller @Controller
public static class MyController {
@RequestMapping
@MyResponseBody
public ResponseData index(@MyRequestBody RequestData requestData) {
System.out.println(requestData);
ResponseData responseData = new ResponseData();
responseData.setData(requestData.getData());
return responseD
注入HandlerAdapter,并加入了两个MyResolver,只不过一个是setCustomArgumentResolvers,另一个是setCustomReturnValueHandlers。MyResolver都加入了DataMessageConvert,这个实现了HttpMessageConverter,稍后会介绍到。 @Configuration
public static class MyWebMvcConfigurationSupport extends WebMvcConfigurationSupport {
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();
List&HttpMessageConverter&?&& converters = new ArrayList&HttpMessageConverter&?&&();
converters.add(new DataMessageConvert());
List&HandlerMethodArgumentResolver& argumentResolvers = new ArrayList&HandlerMethodArgumentResolver&();
argumentResolvers.add(new MyResolver(converters));
requestMappingHandlerAdapter.setCustomArgumentResolvers(argumentResolvers);
List&HandlerMethodReturnValueHandler& returnValueHandlers = new ArrayList&HandlerMethodReturnValueHandler&();
returnValueHandlers.add(new MyResolver(converters));
requestMappingHandlerAdapter.setCustomReturnValueHandlers(returnValueHandlers);
return requestMappingHandlerA
MyResolver继承了AbstractMessageConverterMethodProcessor,并自定义了supportsParameter和supportsReturnType来加载自定义的注解。resolveArgument和handleReturnValue是沿用RequestResponseBodyMethodProcessor的方法,来调用HttpMessageConverter的处理方法。 public static class MyResolver extends AbstractMessageConverterMethodProcessor {
public MyResolver(List&HttpMessageConverter&?&& converters) {
super(converters);
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(MyRequestBody.class);
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
String name = Conventions.getVariableNameForParameter(parameter);
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
public boolean supportsReturnType(MethodParameter returnType) {
return returnType.getMethodAnnotation(MyResponseBody.class) !=
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
mavContainer.setRequestHandled(true);
writeWithMessageConverters(returnValue, returnType, webRequest);
HttpMessageConverter是处理RequestMapping的注释的方法的参数和返回值的接口类。自定义HttpMessageConverter,继承了AbstractGenericHttpMessageConverter来实现一些公用的方法。实现了canRead方法,只解码RequestData这个类,同样实现了canWrite了方法,只编码ResponseData这个类。简便起见这里只编码和解码Map&String, String&,方法也很简单,key和value直接用','链接,不同的entry之间用';'连接。 public static class DataMessageConvert extends AbstractGenericHttpMessageConverter&Object& {
public boolean canRead(Type type, Class&?& contextClass, MediaType mediaType) {
return ((Class) type).isAssignableFrom(RequestData.class);
public boolean canWrite(Type type, Class&?& clazz, MediaType mediaType) {
return ((Class) type).isAssignableFrom(ResponseData.class);
public List&MediaType& getSupportedMediaTypes() {
return Collections.singletonList(MediaType.ALL);
protected boolean supports(Class&?& clazz) {
return clazz.isAssignableFrom(Map.class);
public Object readInternal(Class&?& clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return readMap(inputMessage);
private Object readMap(HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
Charset cs = Charset.forName("UTF-8");
StringBuilder stringBuilder = new StringBuilder();
InputStream inputStream = inputMessage.getBody();
byte[] b = new byte[1024];
while ((length = inputStream.read(b)) != -1) {
ByteBuffer byteBuffer = ByteBuffer.allocate(length);
byteBuffer.put(b, 0, length);
byteBuffer.flip();
stringBuilder.append(cs.decode(byteBuffer).array());
String[] list = stringBuilder.toString().split(";");
Map&String, String& map = new HashMap&String, String&(list.length);
for (String entry : list) {
String[] keyValue = entry.split(",");
map.put(keyValue[0], keyValue[1]);
RequestData requestData = new RequestData();
requestData.setData(map);
return requestD
public void writeInternal(Object o, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
StringBuilder stringBuilder = new StringBuilder();
Map&String, String& map = ((ResponseData) o).getData();
for (Map.Entry&String, String& entry : map.entrySet()) {
stringBuilder.append(entry.getKey()).append(",").append(entry.getValue()).append(";");
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
outputMessage.getBody().write(stringBuilder.toString().getBytes());
public Object read(Type type, Class&?& contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return readMap(inputMessage);
程序入口,跟类似。 @Configuration
public class CustomizeResponseBodyTest {
public static void main(String[] args) throws ServletException, IOException {
MockServletContext mockServletContext = new MockServletContext();
MockServletConfig mockServletConfig = new MockServletConfig(mockServletContext);
AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
annotationConfigWebApplicationContext.setServletConfig(mockServletConfig);
annotationConfigWebApplicationContext.register(CustomizeResponseBodyTest.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(annotationConfigWebApplicationContext);
dispatcherServlet.init(mockServletConfig);
MockHttpServletResponse response = new MockHttpServletResponse();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
request.addHeader("Accept", "application/json");
request.setContent(("result,date," + Calendar.getInstance().getTimeInMillis()).getBytes());
dispatcherServlet.service(request, response);
System.out.println(new String(response.getContentAsByteArray()));
这里主要介绍了HandlerAdapter和HttpMessageConverter。HandlerAdapter封装了HandlerMapping的方法,而HttpMessageConverter则是转换Request和Response的内容的接口,比如json的encode和decode。接下来会介绍更多关于Mvc的内容。@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

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

我要回帖

更多关于 responsewrapper 注解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信