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

一、前提知識:

  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我們下期見吧,休息一下吧)

Tags: