天天看點

SpringBoot傳遞單一參數時@RequestParam和@RequestBody的差別

用SpringBoot架構做項目時,經常需要前端給後端傳遞參數,如果需要多條參數,通常的做法是把這些參數封裝為一個對象來傳遞,前端用POST方式調用。但有時會遇到後端隻需要一條參數(比如一個String)的情況,此時如果還封裝為一個對象,有些麻煩;最好的辦法是用GET方式調用,直接把參數拼接在url後面。然而,一般項目都有統一的接口規範,要求接口都要用POST方式,此時就遇到一個問題:controller方法上到底是用@RequestParam注解還是用@RequestBody注解?

 之前對這兩個注解的差別,隻有一個粗枝大葉的了解——@RequestParam針對單一的參數,而@RequestBody針對多個參數封裝為一個對象,問了身邊幾個同僚,大概也都是這種了解。但是,實際測試中(使用Postman),當我用@RequestParam接受String的單一參數時,前端給我傳遞的參數卻接收不到。于是決定通過實驗,徹底搞明白二者的差別(針對單一參數、且規定使用POST方式的場景)。實驗的過程是分别用兩個注解去接受前端傳遞的一個名為content的String。

實驗一:使用@RequestParam注解

Controller方法代碼:(省略其他部分以及傳回值Result代碼)

@RequestMapping(value="/requestParam", method= RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Result<String> requestParam(@RequestParam("content") String content) {
	System.out.println("content:"+content);
	return success(new Result<String>(), content);
           

現在我用postman來測試幾種可能的參數傳遞方式:

1. 在Body的raw裡面傳遞,也是最通常的傳參方式:

SpringBoot傳遞單一參數時@RequestParam和@RequestBody的差別

結果是接收不到(不管是用text還是json等各種文本形式)!

 { "timestamp": 1544798083474,

    "status": 400,

    "error": "Bad Request",

    "exception": "org.springframework.web.bind.MissingServletRequestParameterException",

    "message": "Required String parameter 'content' is not present",

    "path": "/testParam/requestParam"

  }

2. 在Headers裡通過key-value的形式傳遞。這是網上一些文章裡說的方式。

SpringBoot傳遞單一參數時@RequestParam和@RequestBody的差別

但結果還是接收不到!和上面一樣報錯400。

關于這一點,網上有些文章裡說@RequestParam的參數會寫到Headers裡,可見是錯誤的,并非在Headers裡,還是在Body裡。

3. 在Body的form-data裡通過key-value的形式傳遞,可以接收!

SpringBoot傳遞單一參數時@RequestParam和@RequestBody的差別

但是,前端在傳參時,是無法向這個form-data裡傳遞參數的,是以這種方法隻能被排除。

4. 在url後問号拼接參數。和很多人一樣,之前一直根深蒂固地認為隻有GET方式才能用url問号傳參,POST方式不行,但事實證明在這裡問号傳參POST方式同樣能接收到。如圖:

SpringBoot傳遞單一參數時@RequestParam和@RequestBody的差別

雖然能接受到參數,但前端也有統一的規範,一般不使用問号傳參的方式,是以這種方法也被排除。

實驗二:使用@RequestBody注解

@RequestMapping(value="/requestBody", method= RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Result<String> requestBody(@RequestBody String content) {
	System.out.println("content:"+content);
	return success(new Result<String>(), content);
}
           

既然是Body,自然不能在header裡傳參,也不能在url裡問号傳參。至于Body的form-data,經測試也無效。是以,這裡隻有唯一一種方式,就是将參數直接寫在Body的raw模式下,可以接收到,而且最好選擇Text而非JSON(application/json),如圖:

SpringBoot傳遞單一參數時@RequestParam和@RequestBody的差別

注意:這裡body體裡面傳什麼内容,背景就會原樣接收,是以不要寫成content: XXX這種鍵值對形式,而應直接把String的内容寫在body體裡。

總結:

對于傳遞單一參數(最典型的是String)的場合,最簡便的方法是用GET請求。但鑒于很多項目接口統一要求使用POST方式,此時不能使用@RequestParam方式,因為此方式前端傳遞的參數後端無法接收;而隻能用@RequestBody,直接将需要的參數内容寫入Body體,後端即可正常擷取!