靈活運用的@RequestParam和@RequestBody


最近在編寫項目的過程中,老出現前后端傳遞參數格式不一致、不統一的問題,對於一個已經快工作一年的Java程序員來說,實屬不合格,所以我就下來好好研究了一下@RequestParam和@RequestBody的區別,避免大家遭遇同等錯誤;

一 @RequestParam注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {

	/**
	 * 參數名稱(和value同等意思)
	 */
	@AliasFor("name")
	String value() default "";

	/**
	 * 參數名稱 (和name同等意思)
	 */
	@AliasFor("value")
	String name() default "";

	/**
	 * 是否必選(默認必選)
	 */
	boolean required() default true;

	/**
	 * 參數默認值
	 */
	String defaultValue() default ValueConstants.DEFAULT_NONE;

}

(1)@RequestParam總體上來說,該注解類擁有三個參數:

  a)value、name 屬性都標識請求參數名(必須配置);

  b)required:參數是否必傳,默認為 true,可以設置為非必傳 false;(如果設置了必傳或默認,請求未傳遞參數,將會拋出異常);

  c)defaultValue:參數默認值,如果設置了該值,required 將會自動設置為 false;

(2)@RequestParam注解獲取的參數放在請求哪?

  a)get請求的 requestHeaders 中 content-type 這個字段,使用 form-data 表單形式攜帶參數請求;

  b)Spring中的@RequestParam注解接收的參數大多數場景是來自requestHeaders中,即請求頭,也就是url中,格式為:http://localhost:8080?name=yc&age=23,由於 url 長度有限制,所以參數需要限制數量和值得長度;

(3)如何使用:

  使用一:利用Postman工具,使用form-data提交Get請求

  

  執行代碼:

@RequestMapping(value = "/test", method = RequestMethod.GET)
    public void test(@RequestParam("id") Integer id,
                     @RequestParam("name") String name,
                     @RequestParam("age") Integer age) {
        log.info("id = {}, name = {}, age = {}", id, name, age);
    }

  結果:

id = 1, name = yc, age = 23

  使用二:不使用@RequestParam注解直接進行對象屬性賦值(不推薦使用,容易和@ReuqestBody混淆)

  代碼執行:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

@RequestMapping(value = "/test", method = RequestMethod.GET)
    public void test(User user) {
        log.info("id = {}, name = {}, age = {}", user.getId(), user.getName(), user.getAge());
    }

  結果:

id = 1, name = yc, age = 23

(4)使用場景:

  a)請求是為了查找資源,獲取服務器數據;

  b)請求結果無持續性的副作用,例如:不會對數據庫進行添加、修改、刪除操作;

  c)傳入的參數不會太長,因為Get請求可能會產生很長的URL,或許會超過某些瀏覽器與服務器對URL的長度限制,導致請求失敗;

 二、@RequestBody注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {

	/**
	 * 默認參數必傳
	 */
	boolean required() default true;

}

(1)@RequestBody注解只擁有一個參數:

  required 默認為 true,即對象中的屬性必須有一個要傳,否則會拋出異常:org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

(2)@RequestBody注解獲取的參數在請求哪?

  a)post請求的requestHeaders請求頭中有content-type字段,一般用來處理:applicatin/json格式的參數;

  b)Spring中的@RequestBody注解是用來接收請求體中的參數數據,即requestBody請求體中,故不受參數數據長度的限制;

(3)如何使用?

  使用Postman工具發送json格式的數據:

  

  執行代碼:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Integer age;

}

@RequestMapping(value = "/test", method = RequestMethod.POST)
    public void test(@RequestBody User user) {
        log.info("id = {}, name = {}, age = {}", user.getId(), user.getName(), user.getAge());
    }

  結果:

id = 1, name = yc, age = 23

(4)使用場景:

  a)請求的結果有持續性作用,例如:對數據庫添加、更新、刪除操作;

  b)若使用Get請求,表單參數過長;

  c)要傳送的數據不是采用7位的ASCII編碼;

 

測試三:使用Post請求,@RequestParam也可以接收參數;

  注意:也可以使用這種方式用,發送Post請求,參數拼接到url之后,這是因為協議之間沒有做嚴格的區分,但這種方式不建議使用,這種方式就使用Get方式即可。例如:localhost:8888/optimus-prime/project/test?id=1&name=yc&age=23 使用瀏覽器請求數據,這種方式Get請求,但后端使用Post方式接收,訪問不成功!

  

  執行代碼:

    @PostMapping(value = "/test")
    public void test(@RequestParam("id") Integer id,
                     @RequestParam("name") String name,
                     @RequestParam("age") Integer age) {
        log.info("id = {}, name = {}, age = {}", id, name, age);
    }

  結果:

id = 1, name = yc, age = 12

 

額外知識1:Http協議常用的四種請求方式:Post、Get、Put、Delete等;其中Put、Delete請求方式很少見,都可用Post方式代替!

  a)對數據庫而言: get 請求不修改數據庫,只是查詢。Post是增加記錄,put是更新,Delete數據庫刪除;

  b)Put,Post,Delete 方式的請求參數會直接放在requestBody里;

  c)處理 request uri 部分的注解,路徑參數變量:@PathVariable;

  d)處理request header部分的注解:   @RequestHeader, @CookieValue,@RequestParam;

  e)處理request body部分的注解:@RequestParam, @RequestBody;  

綜上所述:@RequestParam注解既可以接收Get方式的請求頭中的參數,也可以接收Post方式的請求體中的參數;

 

額外知識2:get請求的 headers 中沒有 content-type 這個字段,post 的 content-type 有 :

  a)application/x-www-form-urlencoded  這種就是一般的文本表單用 post 傳地數據,只要將得到的 data 用 @RequestParam 或 request.getParamter() 獲取即可;

  b)multipart/form-data ,用於文件上傳,此時 form 的 enctype 屬性必須指定為 multipart/form-data;

  c)application/json,將數據以json對象的格式傳遞;

  d)text/xml;

  e)put 和 delete 請求的headers 是有 content-type 這個字段的,只不過這兩個方法類型目前不常用;

 

每天進步一點點,開心!  

 

 

  

 


免責聲明!

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



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