@RequestParam,@RequestBody,@ResponseBody,@PathVariable註解的一點小總結

碼農Amg發表於2020-09-26

一、前提知識:

  1. http協議規定一次請求對應一次響應,根據不同的請求方式,請求的內容會有所不同;

  2. 傳送GET請求是沒有請求體的,引數會直接拼接保留到url後一併傳送;

  3. 而POST請求是帶有請求體的,帶著請求體一併傳送,每次請求請求體只會有一個;

二、註解介紹

@RequestParam註解:將返回到後端的請求引數繫結到控制器方法引數,該註解有兩個需要了解的屬性

  1. 一個是required屬性,預設是true

    當該屬性為true的時候,且指定了value屬性時,如果前臺頁面的key跟接收的value不同是是會報400錯誤的;

    而當該屬性為false的是會,即使key不存在,也不會報400的錯;

    ⚠️但是當後面的引數的基本資料型別的時候,是會報500錯誤的,因為當找不到值的時候,會預設返回一個null,基本資料型別接收到null,直接就會報錯,解決方法就是使用對應的引用型別去接收,即使時null也不會報錯

     

  2. 另一個是defaultValue屬性,預設值是16個Unicode字元

    使用了該屬性之後,且指定了value屬性,但是前端頁面並沒有給對應的key時,就會預設採用這個自動值,底層會幫我們自動轉換成引數型別

⚠️ 繫結的方法引數是附加到url後的[key-value]格式的值,進而衍生出也可以是陣列、物件或者集合,接下來會進行演示

 

@RequestBody跟@ResponseBody:這兩個註解的作用其實是一樣的,處理的都是json字串,只不過前一個註解是從前往後傳,第二個註解是從後往前傳,接下來也會樣式這兩個註解的使用方式

⚠️ 所以講到這裡其實應該明白,@RequestBody註解在一個方法中只會出現一次,而@RequestParam則可以出現多個,這是因為@RequestBody接收的是整個請求體的json格式化字串,而@RequestParam接收的是附加到url後面的[key-value]形式值,會存在多個這樣的值,所以自然也可以使用多個@RequestParam註解來接收,如果是較少的引數那還好,如果太多的引數,一個一個獲取就太麻煩了,而且寫出來的程式碼也不夠優雅整潔。

@PathVariable的作用其實就是接收url後面傳過來的變數,這個註解使用起來很簡單

 

三、註解的簡單演示

是基於springboot環境,使用postman來測試

一、@RequestParam註解

  1. 簡單使用,接收url後面的 key-value值

    //測試的介面 : localhost:8080/testRequestParam/one?name=Amg&age=22
    ​
    @RestController
    @RequestMapping("/testRequestParam")
    public class TestRequestParamAnno {
    ​
        @GetMapping("/one")
        public Result one(@RequestParam(value = "name") String name,
                          @RequestParam(value = "age") int age){
            
            System.out.println(name + " / " + age);
            return ResultGenerator.getSuccessful(name + " / " + age);
        }
    ​
    }
    ​
    //output ResultGenerator返回的是一個物件,通過@ResponseBody轉換成json字串格式
    {
        "code": 200,
        "msg": "Amg / 22"
    }

     

     

    2.測試新增required屬性跟defaultValue屬性

    //測試的介面: localhost:8080/testRequestParam/two?name=Amg&=
    ​
    @GetMapping("/two")
    public Result two(@RequestParam(value = "name") String name,
                      @RequestParam(value = "age") int age) {
    ​
        System.out.println(name + " / " + age);
        return ResultGenerator.getSuccessful(name + " / " + age);
    }
    ​
    //output 這是由於返回的url中沒有 age 這個key,所以報400錯誤,這是很常見的一種錯誤
    {
        "timestamp": "2020-09-26T07:22:51.449+00:00",
        "status": 400,
        "error": "Bad Request",
        "trace": "org.springframework.web.bind.MissingServletRequestParameterException: Required int parameter 'age' is not present
        "message": "Required int parameter 'age' is not present",
        "path": "/testRequestParam/two"
    }
    ​
    //此時可以通過給預設值來解決
    @GetMapping("/two")
    public Result two(@RequestParam(value = "name") String name,
                      @RequestParam(value = "age" ,defaultValue = "1") int age) {
    ​
        System.out.println(name + " / " + age);
        return ResultGenerator.getSuccessful(name + " / " + age);
    }
    ​
    //output
    {
        "code": 200,
        "msg": "Amg / 1"
    }

     

     

    3.如果url後有多個key值,那麼如此一個一個的接收就會顯得很麻煩,而且方法引數也會很膨脹,一點都不優雅,其實我們還可以這樣操作

    //這種寫法就會使得方法引數很膨脹(不建議使用),其實我們只需要改造一下
    public Result three(@RequestParam(value = "name") String name,
                        @RequestParam(value = "age") int age,
                        @RequestParam(value = "gender") String gender,
                        @RequestParam(value = "lover") String lover,
                        @RequestParam(value = "weight") double weight ){
    ​
    }
    ​
    //用一個Map來接收所有的key,value值
    @GetMapping("three")
    public Result three(@RequestParam Map<String,Object> map){
    ​
        StringBuilder sb = new StringBuilder();
        map.forEach((key,value) -> {
            sb.append(key + " / " + value + "; ");
        });
        return ResultGenerator.getSuccessful(sb.toString());
    }
    ​
    //output
    {
        "code": 200,
        "msg": "name / Amg; age / 22; gender / 男; lover / guess; weight / guess; "
    }

     

     

二、@Requestbody和@ResponseBody

//首先構造一個物件,使用lombok外掛給getter/setter和tostring方法
​
@Data
@ToString
public class User {
    
    private String name;
    
    private Integer age;
    
    private String gender;
}

 


1.接收前臺返回來的json字串,並且封裝到User物件裡面

(題外話:前臺頁面可以使用JSON.stringify函式把元素打成json串,指定內容格式為json,傳送ajax請求到後臺)

@GetMapping("/one")
@ResponseBody
public Result one(@RequestBody User user){
    return ResultGenerator.getSuccessful(user.toString());
}
​
//預估會接收一個json串,然後又傳回去(別糾結,只是做演示,正常會有邏輯操作)

 

 

發生了405錯誤,這是因為我們在錯誤的地方使用了POST請求,後臺接收用了Get請求,沒有對上,這也是非常常見的錯誤,修改方法也很簡單

把後臺的Get請求修改成Post請求(一般使用這種)

前臺傳送Get請求

//修改過後
//output
{
    "code": 200,
    "msg": "User(name=Amg, age=22, gender=男, motto=該吃吃,該喝喝,遇事別往心裡擱)",
    "data": null
}

 

至於@ResponseBody註解的演示,可是一直有在用,返回去的格式就是json格式串

三、@PathVariable

剛剛說了,該註解是接收url後面的變數的,使用起來也很方便,看一個小例子

//測試的介面:localhost:8080/testPathVariable/one/3024166
​
@GetMapping("/one/{id}")
public Result one(@PathVariable("id") String id){
    return ResultGenerator.getSuccessful("接收回來的路徑是:" + id);
}
​
//output
{
    "code": 200,
    "msg": "接收回來的路徑是:3024166",
    "data": null
}

 

以上註解都是日常工作中會用到的,今天抽了點時間做個小總結... 是時候打遊戲去了(遊戲不香嘛!!)

最後,感謝你的觀看,如果覺得有收穫的話,請幫忙點個贊

(關注公眾號:碼農Amg ,一位剛畢業的搬磚工,會不定期的分享工作中遇到的坑和學習小總結,時常還會分享沙雕日常,歡迎胖友們一起溝通交流)

一起努力學習,天天向上(emmm我們下期見吧,休息一下吧)

相關文章