本文摘自:http://www.cnblogs.com/zhaoyang/archive/2012/01/07/2315436.html
@ResponseBody & @RequestBody
作用?
@RequestBody 將 HTTP 請求正文插入方法中,使用適合的HttpMessageConverter將請求體寫入某個對象。
@ResponseBody 將內容或對象作爲 HTTP 響應正文返回,使用@ResponseBody將會跳過視圖處理部分,而是調用適合HttpMessageConverter,將返回值寫入輸出流。
HttpMessageConverter接口
<mvc:annotation-driven />開啓了之後它給AnnotationMethodHandlerAdapter初始化7個轉換器,可以通過調用AnnotationMethodHandlerAdapter類的getMessageConverts()方法來獲取轉換器的一個集合 List<HttpMessageConverter>
默認給AnnotationMethodHandlerAdapter初始化的有(當然我們也可以添加自定義的converter)
ByteArrayHttpMessageConverter
StringHttpMessageConverter
ResourceHttpMessageConverter
SourceHttpMessageConverter<T>
XmlAwareFormHttpMessageConverter
Jaxb2RootElementHttpMessageConverter
MappingJacksonHttpMessageConverter
Spring是如何尋找最佳的HttpMessageConverter
1 首先獲取註冊的所有HttpMessageConverter集合
2 然後客戶端的請求header中尋找客戶端可接收的類型,
比如 Accept application/json,application/xml等,組成一個集合
3 所有的HttpMessageConverter 都有canRead和canWrite方法 返回值都是boolean,看這個HttpMessageConverter是否支持當前請求的讀與寫,讀對應@RequestBody註解, 寫對應@ResponseBody註解
4 遍歷HttpMessageConverter集合與前面獲取可接受類型進行匹配,如果匹配直接使用當前第一個匹配的HttpMessageConverter,然後return(一般是通過Accept和返回值對象的類型進行匹配)
例如
StringHttpMessageConverter
支持String , Accept所有類型
MappingJacksonHttpMessageConverter
支持Map List 實體對象等等 ,Accept:application/json
示例:
目標:
使用ResponseBody根據head的Accept不同對同一地址請求分別來呈現一個實體的json與xml結果
由於<context:annotation-config />
默認會初始化AnnotationMethodHanlderAdapter,但我們返回xml內容需要對這個HandlerAdapter進行一定的修改,所以配置文件如下:
<context:component-scan base-package="com.controls" />
<context:annotation-config />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="stringHttpMessageConverter" />
<ref bean="jsonHttpMessageConverter" />
<ref bean="marshallingHttpMessageConverter" />
</list>
</property>
</bean>
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxbMarshaller" />
<property name="supportedMediaTypes" value="application/xml"></property>
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.model.User</value>
</list>
</property>
</bean>
注:要使用Jaxb2Marshaller我們在對應的實體,比如User類上需要標明
@XmlRootElement 註解,需要引入
import javax.xml.bind.annotation.XmlRootElement;
這個包。
Controller中應對請求的方法
@RequestMapping(value="/user/{userid}", method=RequestMethod.GET)
public @ResponseBody User queryUser(@PathVariable("userid") long userID) {
Calendar d = Calendar.getInstance();
d.set(1987, 12, 9);
User u = new User();
u.setUserID(userID);
u.setUserName("zhaoyang");
u.setBirth(d.getTime());
return u;
}
接着我們使用curl這個工具進行測試
如下圖: