一:@RequestBody和@RequestParam區別
@RequestParam
用來處理Content-Type: 為 application/x-www-form-urlencoded編碼的內容。(Http協議中,如果不指定Content-Type,則默認傳遞的參數就是application/x-www-form-urlencoded類型)
RequestParam可以接受簡單類型的屬性,也可以接受對象類型。
實質是將Request.getParameter() 中的Key-Value參數Map利用Spring的轉化機制ConversionService配置,轉化成參數接收對象或字段。
tip
在Content-Type: application/x-www-form-urlencoded的請求中,
get 方式中queryString的值,和post方式中 body data的值都會被Servlet接受到並轉化到Request.getParameter()參數集中,所以@RequestParam可以獲取的到。
@RequestBody
處理HttpEntity傳遞過來的數據,一般用來處理非Content-Type: application/x-www-form-urlencoded編碼格式的數據。
GET請求中,因為沒有HttpEntity,所以@RequestBody並不適用。
POST請求中,通過HttpEntity傳遞的參數,必須要在請求頭中聲明數據的類型Content-Type,SpringMVC通過使用HandlerAdapter 配置的HttpMessageConverters來解析HttpEntity中的數據,然后綁定到相應的bean上。
總結
在GET請求中,不能使用@RequestBody。
在POST請求,可以使用@RequestBody和@RequestParam,但是如果使用@RequestBody,對於參數轉化的配置必須統一。
舉個例子,在SpringMVC配置了HttpMessageConverters處理棧中,指定json轉化的格式,如Date轉成‘yyyy-MM-dd’,則參數接收對象包含的字段如果是Date類型,就只能讓客戶端傳遞年月日的格式,不能傳時分秒。因為不同的接口,它的參數可能對時間參數有不同的格式要求,所以這樣做會讓客戶端調用同事對參數的格式有點困惑,所以說擴展性不高。
如果使用@RequestParam來接受參數,可以在接受參數的model中設置@DateFormat指定所需要接受時間參數的格式。
另外,使用@RequestBody接受的參數是不會被Servlet轉化統一放在request對象的Param參數集中,@RequestParam是可以的。
綜上所述,一般情況下,推薦使用@RequestParam注解來接受Http請求參數。
二:GET請求可以使用@RequestBody來接收參數嗎?
答案是可以的。
為什么會這樣呢?感覺要懷疑人生了,GET與@RequestParam,POST與@RequestBody才是我們映像中的絕配。
其實在一般的情況下,GET請求是不可以用@RequestBody來接收參數的。一般情況指的是請求由瀏覽器或者類似於POSTMAN這樣的測試工具發出,我們都知道,Http請求包含請求頭和請求體,如果發出的請求中請求體為空,那么使用@RequestBody注解來獲取參數肯定是徒勞的,所以在這種情況下,GET與@ReqestBody配合使用是有問題的。
那么在什么情況下可以配合使用呢?需要兩個條件,一是請求方式為GET,二是請求參數寫入請求體中。即接口需要被上層的服務調用而非頁面直接訪問。由於目前微服務的運用越來越多,所以一般像這樣的情況在實際的開發中會變得常見。
像這樣的接口如何測試呢?可以使用curl命令,事例如下:curl -XGET -H "Content-Type:application/json" "http://host:port/requestmapping" -d '{"paramId":[1,2,3]}'