HttpMessageConverter


HttpMessageConverter<T>是Spring3的一個重要接口,它負責將請求信息轉換為一個對象(類型為T),將對象(類型為T)輸出為響應信息。

DispatcherServlet默認已安裝RequestMappingHandlerAdapter作為HandlerAdapter的組件實現類,HttpMessageConverter即由RequestMappingHandlerAdapter使用,將請求信息轉換為對象,或將對象轉換為響應信息。

HttpMessageConverter<T>接口定義以下幾個方法:

/**
 * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
 */
public interface HttpMessageConverter<T> {

    /**
     * Indicates whether the given class can be read by this converter.
     */
    boolean canRead(Class<?> clazz, MediaType mediaType);

    /**
     * Indicates whether the given class can be written by this converter.
     */
    boolean canWrite(Class<?> clazz, MediaType mediaType);

    /**
     * Return the list of {@link MediaType} objects supported by this converter.
     */
    List<MediaType> getSupportedMediaTypes();

    /**
     * Read an object of the given type form the given input message, and returns it.
     */
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException;

    /**
     * Write an given object to the given output message.
     */
    void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException;

}

Spring為HttpMessageConverter提供了眾多的實現類

RequestMappingHandlerAdapter默認已經注冊了以下HttpMessageConverter:

private List<HttpMessageConverter<?>> messageConverters;
public RequestMappingHandlerAdapter() {
    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
    stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316
    this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
    this.messageConverters.add(new ByteArrayHttpMessageConverter());
    this.messageConverters.add(stringHttpMessageConverter);
    this.messageConverters.add(new SourceHttpMessageConverter<Source>());
    this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}

 如果需要裝配其他類型的HttpMessageConverter,可以在Spring的web容器(Spring子容器)上下文中自行定義一個RequestMappingHandlerAdapter,注冊若干HttpMessageConverter。dispatcher-servlet.xml

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters" ref="messageConverters"/>
</bean>
<!--HttpMessageConverter列表-->
<util:list id="messageConverters">
    <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</util:list>

 如果在Spring web容器中顯式定義了一個RequestMappingHandlerAdapter,則Spring MVC將使用它覆蓋默認的AnnotationMethodHandlerAdapter(默認配置就沒有了)。

如何使用 HttpMessageConverter<T> 將請求信息轉換並綁定到處理方法的入參中或將響應結果轉為對應類型的響應信息,Spring MVC提供了兩種途徑:

1. 使用@RequestBody/@ResponseBody 對處理方法進行標注

2. 使用HttpEntity<T>/ResponseEntity<T> 作為處理方法的入參或返回值

示例1:

@RequestMapping(value = "/handle41") public String handle41(@RequestBody String requestBody){ //將請求-報文體-轉換為字符串綁定到requestBody入參中
} @ResponseBody @RequestMapping("/handle42") public byte[] handle42(){ // }

 handle41()處Spring MVC將根據requestBody的類型(String)查找匹配的HttpMessageConverter由於StringHttpMessageConverter的泛型類型對應String,所以StringHttpMessageConverter將會被Spring MVC選中,用它將請求體(POST)信息進行轉換並且將結果綁定到requestBody入參上!

handle42()處,由於方法的返回值類型為byte[],所以Spring MVC根據類型匹配的查找規則將使用ByteArrayHttpMessageConverter對返回值進行處理。

和@RequestBody/@ResponseBody類似,HttpEntity<?>不但可以訪問請求和響應報文頭的數據,還可以訪問請求和響應報文體的數據(也就是HttpEntity中不但有頭數據還有體數據),Spring MVC根據HttpEntity的泛型類型查找對應的HttpMessageConverter

在接收到一個http請求的時候,處理方法如何知道請求消息的格式,在處理完成之后又根據什么確定響應消息的格式?答案很簡單,根據請求消息頭的"Content-Type"及Accept屬性確定。

Content-Type表示本次請求的報文內容格式。

Accept表示接受的MIME類型。

例如:
@ResponseBody @RequestMapping( "/getEmployeesForJson") public Collection<Employee> getEmployees() { return employeeDao .getAll(); }
 請求時的目標類型:
方法的實際返回值為:Employee 的集合
SpringMVC 發現需要返回的是JSON類型,但實際返回的是Employee的集合。此時@ResponseBody查找有沒有把結果轉為JSON 的HttpMessageConverter,如果有,則調用其對應的方法,把結果轉為JSON類型。
結論:
1.只有當處理器方法使用到@RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 時,SpringMVC才使用注冊的HttpMessageConverter 對請求響應消息進行處理。
2.當控制器處理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 時,Spring 首先根據請求頭或響應頭的 Accept 屬性選擇匹配的 HttpMessageConverter, 然后根據參數類型或泛型類型的過濾得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 將報錯
3.@RequestBody 和 @ResponseBody 不需要成對出現。如果方法入參使用到了@RequestBody,SpringMVC將會選擇匹配的HttpMessageConverter 將請求信息轉換並綁定到該入參中。如果處理方法標注了@ResponseBody,SpringMVC選擇匹配的HttpMessageConverter 將方法返回值轉換並輸出響應消息。


免責聲明!

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



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