2015-04-08 55 views
5

我正在研究Spring如何處理REST web服務和我對HttpMessageConverter的概念有一些疑問。@RequestBody註釋的工作原理以及它如何與HttpMessageConverter接口相關?

在官方文檔,我可以讀:

策略接口來指定,可以從 和HTTP請求和響應轉換器。

所以HttpMessageConverter似乎是一個接口,但究竟什麼是策略接口?是否與策略模式有關?

所以我得從什麼瞭解Spring自動默認提供註冊一些實現使用@EnableWebMvc

當但究竟是什麼,這些實施?你能給我一個實際的例子嗎?

我認爲它的工作過程是這樣:

例如客戶端執行一個HttpRequest把這個請求JSON郵件的正文(我不是那麼實用,但我認爲我可以做一些事情像這樣),那麼處理這個HttpRequst的控制器使用HttpMessageConverter的實現來將這個JSON消息轉換爲模型對象。我認爲這也是正確的,反之亦然。

我的推理是否正確或我錯過了什麼?

另一個疑問是關於@RequestBody註釋(我認爲它與前一個主題有關)。

我有這樣的例子:

@RequestMapping(value="/orders/{id}", method=RequestMethod.PUT) 
@ResponseStatus(HttpStatus.NO_CONTENT) // 204 
public void updateOrder(@RequestBody Order updatedOrder, @PathVariable("id") long id) { 
    // process updated order data and return empty response 
    orderManager.updateOrder(id, updatedOrder); 
} 

所以我認爲@RequestBody訂購updatedOrder採取updatedOrder輸入參數的值從身體HttpRequest中,然後用它轉換成一個訂購對象使用執行HttpMessageConverter

這是對的還是我錯過了什麼?如果它是正確的,怎麼才能選擇正確的轉換器?

例如在這裏我發現了另一個例子類同前一個:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

@Controller 
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 
public void addPet(@RequestBody Pet pet, Model model) { 
    // implementation omitted 
} 

我認爲這是明確指出,它必須使用JSON來Model對象轉換器。爲什麼在前面的例子中沒有指定?如何選擇正確的轉換器?

TNX

回答

9

處理程序方法參數由Spring的HandlerMethodArgumentResolver和處理方法的返回值來生成由Spring的HandlerMethodReturnValueHandler處理。處理@ResponseBody@RequestBody的實現是RequestResponseBodyMethodProcessor

其中之一是默認註冊(@EnableWebMvc配置),默認列表爲HttpMessageConverter實例。這在WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)完成。您可以找到源代碼並查看添加的內容和順序。

春去生成用於@RequestBody參數的參數,它循環通過HttpMessageConverter情況下,檢查是否該實例HttpMessageConverter#canRead內容類型中的給定的請求,並且可以生成參數類型的實例。如果可以的話,Spring將使用該HttpMessageConverter來產生一個參數。如果不行,Spring會跳過它並嘗試下一個實例,直到它耗盡。在這一點上,它會拋出一個異常。

對於@ResponseBody,除Spring現在使用HttpMessageConverter#canWrite外,其他過程是相同的。它將檢查HttpMessageConverter是否可以序列化返回類型並生成符合響應中預期的內容類型(在Accept請求標頭中給出)的響應內容。

@RequestParam

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 

consumes屬性無關,與上述聲明的策略。 consumes在這裏所做的唯一事情是限制處理程序的映射。例如,把這些兩個處理程序

@RequestMapping(value = "/pets", method = RequestMethod.POST) 

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 

第一種可以處理任何內容類型/pets的任何請求。第二個只能處理/pets這些內容類型爲application/json的請求。

+3

完美的解釋,你是一個忍者,爲你而生 – AndreaNobili

相關問題