HttpMessageConverter(消息轉換器 )和@responsebody使用(轉)


@responsebody表示該方法的返回結果直接寫入HTTP response body中
一般在異步獲取數據時使用,在使用@RequestMapping后,返回值通常解析為跳轉路徑,加上@responsebody后返回結果不會被解析為跳轉路徑,而是直接寫入HTTP response body中。比如異步獲取json數據,加上@responsebody后,會直接返回json數據。
Spring3 MVC的@ResponseBody 的作用是把返回值直接寫到HTTP response body里。

Spring MVC 中的 REST 支持

@Controller

使用 @Controller 注釋對將成為 MVC 中控制器的類進行注釋並處理 HTTP 請求。

@RequestMapping

使用 @RequestMapping 注釋對函數進行注釋,該函數處理某些 HTTP 方法、URI 或 HTTP 頭。此注釋是 Spring REST 支持的關鍵。可以更改 method 參數以處理其他 HTTP 方法。

HttpMessageConverter
HTTP 請求和響應是基於文本的,意味着瀏覽器和服務器通過交換原始文本進行通信。但是,使用 Spring,controller 類中的方法返回純 ‘String’ 類型和域模型(或其他 Java 內建對象)。如何將對象序列化/反序列化為原始文本?這由HttpMessageConverter 處理。

Http請求和響應報文本質上都是一串字符串,當請求報文來到java世界,它會被封裝成為一個ServletInputStream的輸入流,供我們讀取報文。響應報文則是通過一個ServletOutputStream的輸出流,來輸出響應報文。

我們從流中,只能讀取到原始的字符串報文,同樣,我們往輸出流中,也只能寫原始的字符。而在java世界中,處理業務邏輯,都是以一個個有業務意義的對象為處理維度的,那么在報文到達SpringMVC和從SpringMVC出去,都存在一個字符串到java對象的阻抗問題。這一過程,不可能由開發者手工轉換。我們知道,在Struts2中,采用了OGNL來應對這個問題,而在SpringMVC中,它是HttpMessageConverter機制。我們先來看兩個接口。

對消息轉換器最高層次的接口抽象,描述了一個消息轉換器的一般特征,我們可以從這個接口中定義的方法,來領悟Spring3.x的設計者對這一機制的思考過程。

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。

我們可以用下面的圖,簡單描述一下這個過程。

 

 

在我們對SpringMVC源碼分析的過程中,我們可以從HttpMessageConverter機制中領悟到類似的道理。在SpringMVC的設計者眼中,一次請求報文和一次響應報文,分別被抽象為一個請求消息HttpInputMessage和一個響應消息HttpOutputMessage。

處理請求時,由合適的消息轉換器將請求報文綁定為方法中的形參對象,在這里,同一個對象就有可能出現多種不同的消息形式,比如json和xml。同樣,當響應請求時,方法的返回值也同樣可能被返回為不同的消息形式,比如json和xml。

在SpringMVC中,針對不同的消息形式,我們有不同的HttpMessageConverter實現類來處理各種消息形式。但是,只要這些消息所蘊含的“有效信息”是一致的,那么各種不同的消息轉換器,都會生成同樣的轉換結果。至於各種消息間解析細節的不同,就被屏蔽在不同的HttpMessageConverter實現類中了。

表 1. HttpMessageConverter 示例:

 

 

配置 HttpMessageConverter。要生成多個具象,自定義幾個 HttpMessageConverter 實例,以將對象轉換為不同的媒體類型。此部分包括 JSON、ATOM 和 XML 媒體類型。

JSON
從最簡單的示例開始。JSON 是一個輕量型的數據交換格式,人們可輕松地進行讀取和編寫。清單 1 顯示了配置 JSON converter 的代碼。

清單 1. 配置 rest-servlet.xml 中的 HttpMessageConverter

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
   <property name="messageConverters">
       <list>
           <ref bean="jsonConverter" />
           <ref bean="marshallingConverter" />
           <ref bean="atomConverter" />
       </list>
   </property>
</bean>

<bean id="jsonConverter"   class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
   <property name="supportedMediaTypes" value="application/json" />
</bean>

MappingJacksonHttpMessageConverter 用於將對象轉換為 JSON,反之亦然。此內置轉換程序使用 Jackson 的 ObjectMapper 將 JSON 映射到 JavaBean,因此您必須將下列 Jackson JAR 文件添加到類路徑。
org.codehaus.jackson.jar
org.codehaus.jackson.mapper.jar

下一步是編寫一個方法,處理請求 JSON 具象的請求。清單 2 顯示了詳細信息
清單 2. 處理在 EmployeeController 中定義的 JSON 請求

@RequestMapping(method=RequestMethod.GET, value="/emp/{id}", headers="Accept=application/json")
public @ResponseBody Employee getEmp(@PathVariable String id) {
    Employee e = employeeDS.get(Long.parseLong(id));
    return e;
}

@RequestMapping(method=RequestMethod.GET, value="/emps", headers="Accept=application/json")
public @ResponseBody EmployeeListinggetAllEmp() {
    List<Employee> employees = employeeDS.getAll();
    EmployeeListinglist = new EmployeeList(employees);
    return list;
}

@ResponseBody 注釋用於將返回對象(Employee 或 EmployeeList)變為響應的正文內容,將使用 MappingJacksonHttpMessageConverter 將其映射到 JSON。

使用 HttpMessageConverter 和 @ResponseBody,您可以實現多個具象,而無需包含 Spring 的視圖技術 — 這是使用 ContentNegotiatingViewResolver 所不具有的一個優勢。

Spring3 MVC的@ResponseBody 的作用是把返回值直接寫到HTTP response body里。 使用AnnotationMethodHandlerAdapter的handleResponseBody方法, AnnotationMethodHandlerAdapter使用request header中”Accept”的值和messageConverter支持的MediaType進行匹配,然后會用”Accept”的第一個值寫入 response的”Content-Type”。

AnnotationMethodHandlerAdapter將會初始化7個轉換器,可以通過調用AnnotationMethodHandlerAdapter的getMessageConverts()方法來獲取轉換器的一個集合
————————————————
版權聲明:本文為CSDN博主「21989939」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_21989939/article/details/46739567

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM