目錄

Day 19 - 取得請求參數(上)- @RequestParam、@RequestBody

古古

2024/07/19


哈囉大家好,我是古古。

在上一篇文章中,我們先介紹了 Http method 的概念,並且也介紹了兩個常見的 Http method:GET 和 POST,分別了解他們是如何傳遞參數給後端的。

那麼接著這篇文章,我們就會回到 Spring Boot 上,來介紹一下要如何在 Spring Boot 中,去接住前端所傳過來的這些參數的值。

補充:不過也因為在 Spring Boot 有許多種方式可以接住前端所傳遞過來的參數,因此這裡會分成上、下兩篇文章來介紹,因此這篇文章我們就會先介紹 @RequestParam@RequestBody 的用法。

在 Spring Boot 中接住參數的四個註解 #

在 Spring Boot 中,有四個註解可以去接住前端傳遞過來的參數,分別是:

  1. @RequestParam
  2. @RequestBody
  3. @RequestHeader
  4. @PathVariable

這四個註解雖然長得有點像(都是以 @Request 開頭),但是他們功能是完全不同的!所以接下來這兩篇文章,我們就會分別來介紹這四個註解要如何使用。

而在這篇文章中,我們就會先來介紹前兩個註解,也就是 @RequestParam@RequestBody 的用法。

1. @RequestParam:接住添加在 url 後面的參數 #

首先我們先來看第一個註解,也就是 @ReqeustParam

@ReqeustParam 的用途,就是「接住那些放在 url 後面的參數」,所以像是我們在上一個章節中所介紹到的 GET 請求,就是會把請求參數放在 url 的最後面來傳遞:

因此當前端使用 GET 來請求時,我們就可以在 Spring Boot 中寫上 @ReqeustParam,去接住前端所傳遞過來的參數(query parameter)。

在 Spring Boot 中練習 @RequestParam 的用法 #

大概了解了 @ReqeustParam 的概念之後,我們也可以實際到 Spring Boot 上來練習一下 @ReqeustParam 的用法。

舉例來說,當前端使用 GET 來請求、並且在 url 的最後面加上了一個 id=123 的參數時,那麼前端的實際請求就會如下圖所示:

而這個時候,如果我們想要在 Spring Boot 中去接住 id=123 的參數的話,那我們就可以像下圖一下,先在 test1() 方法中,新增一個 Integer 類型的參數 id,並且在 id 的前面加上一個 @RequestParam,這樣子就可以成功的取得到前端傳遞過來的 id=123 的值了!

所以如果我們實際到 Spring Boot 上練習的話,就只要改寫一下 MyController,將他改成下面的程式:

@RestController
public class MyController {

    @RequestMapping("/test1")
    public String test1(@RequestParam Integer id) {
        System.out.println("id 的值為: " + id);
        return "請求成功";
    }
}

寫上上述的程式之後,就可以運行一下 Spring Boot 程式。

運行成功之後回到 API Tester 上,接著在 Http method 中選擇 GET 請求,url 填上 http://localhost:8080/test1?id=123,這樣子就可以模擬前端的請求。

因此當我們按下 Send 鍵之後,在右下角的 response body 中,就會出現 Spring Boot 所回傳的「請求成功」的訊息。

此時當我們回到 IntelliJ 上查看的話,在下方的 console 中,就會出現「id 的值為: 123」的字串。

所以這就表示,我們就成功的透過 @RequestParam,接住前端放在 url 中所傳遞的參數了!

使用 @RequestParam 的注意事項之一:參數名字須一致 #

在使用 @RequestParam 去接住 url 後面的參數時,首先有一個重點需要注意,就是在 Spring Boot 中的「變數的名字」,必須要和「url 中的參數的名字」一樣才可以。

舉例來說,假設 url 中所添加的參數是 id=123,那麼在 Spring Boot 所使用的參數名字,就必須也是 id;又或是說假設 url 中添加的是 name=Judy,那麼在 Spring Boot 中所使用的參數名字,就必須是 name

假設參數名字不一致的話,@RequestParam 是沒有辦法成功取得到 url 中的參數的,因此大家在使用上,就要特別注意這兩個地方的名字一定要一致才可以!

補充:如果真的發生參數名字不一樣的情況出現,那麼透過一些額外的設定,其實也是可以讓 @RequestParam 生效的。

舉例來說,假設前端傳遞的參數為 myId=123,但是如果想要在 Spring Boot 上使用 id 來接住這個 myId 的參數的話,那麼就要改寫成 @RequestParam(name = "myId") Integer id) 的寫法(也就是在 @RequestParam 後面多加上了 (name = "myId") 的額外設定),這樣子才能夠將前端的 myId 對應到 Spring Boot 中的 id 參數。

不過雖然 @RequestParam 有支援這種特殊的設定,但一般在實作上,還是會建議大家盡量讓「前端傳遞的參數」和「Spring Boot 中使用的參數名稱」一致,這樣子就不用多寫額外的程式來轉換,實作上也比較直覺方便,比較不會出問題。

使用 @RequestParam 的注意事項之二:參數類型需一致 #

使用 @RequestParam 去接住 url 參數的第二個重點,就是「參數的類型需要一致」。

舉例來說,假設前端在 url 中所添加的參數是 id=123,那麼就是在暗示這個 id 的值是一個整數,因此我們在 Spring Boot 中,就需要將該參數宣告為 Integer 類型或是 int 類型,這樣才能成功接住前端所傳過來的參數。

又或是前端在 url 中所添加的參數是 name=Judy,那麼就是在暗示這個 name 參數的值是一個字串,因此我們在 Spring Boot 中,就需要將該參數宣告為 String 類型,這樣也才能成功接住前端所傳過來的參數。

因此只有當類型一致時,Spring Boot 才有辦法成功的接住該參數,將該參數的值給轉換過來,否則的話 Spring Boot 可是會出錯的!會回傳一個請求失敗的資訊給前端。

小結:@RequestParam 用法總結 #

綜合以上的介紹,我們可以先做個 @RequestParam 的用法總結。

@RequestParam 的用途,就是「接住那些放在 url 後面的參數」,所以當前端將參數添加在 url 的後面來傳遞時,就是 @RequestParam 出馬的時候了!

而在使用 @RequestParam 時,要注意以下的事項:

  • 參數的名字要一致(無額外的設定下)
  • 參數的類型要一致

只要掌握好上面兩個注意事項,就可以成功的運用 @RequestParam,去接住前端放在 url 後面的那些參數了!

2. @RequestBody:接住放在 request body 中的參數 #

了解了 @RequestParam 的用法之後,接著我們可以來看第二個註解 @RequestBody 的用法。

@RequestBody 的用途,就是「接住放在 request body 中的參數」,所以像是我們在上一篇文章中所介紹到的 POST 請求,他就是會把參數放在 request body 中來傳遞:

因此當前端使用 POST 來請求時,我們就可以在 Spring Boot 中寫上 @ReqeustBody,去接住前端放在 request body 中所傳遞的參數。

在 Spring Boot 中練習 @RequestBody 的用法 #

大概了解了 @ReqeustBody 的概念之後,我們一樣也是可以實際到 Spring Boot 中,來練習一下 @ReqeustBody 的用法。

舉例來說,當前端使用 POST 來請求、並且在 request body 中添加了下列的 JSON 格式的參數的話,那麼前端的實際請求就會如下圖所示:

而這個時候,如果我們想要在 Spring Boot 中去接住這個 JSON 格式的參數的話,那我們首先要做的,就是先去創建一個 Java class 出來,並且這個 Java class 中的變數,會和 JSON 格式的數據「一一對應」。

像是我們可以先去 new 一個 Student class 出來,並且在 Student 中添加下列的程式:

public class Student {

    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

當我們這樣寫時,就是去創建了一個「和 JSON 數據一一對應的 Student class」出來。

之所以說這個 Student class 和 JSON 數據一一對應,是因為在上述的 JSON 數據中,他裡面有兩個 key 存在,分別是 id(整數)和 name(字串),而在 Student class 中也有兩個變數存在,變數名稱也是 id 和 name,並且 id 也為整數類型、name 也為字串類型。

而當我們創建出「和 JSON 數據一一對應的 Student class」之後,Spring Boot 到時候就會自動將 request body 中的 JSON 參數,一口氣轉換成 Student class 了!magic!!

寫好 Student class 之後,接著我們可以回到 MyController,並且在裡面新增另一個方法 test2(),接著我們在 test2() 中先新增一個 Student 類型的參數 student,並且在這個 name 的前面,加上一個 @RequestBody,如下方程式所示:

@RequestMapping("/test2")
public String test2(@RequestBody Student student) {
    System.out.println("student 中的 id 值為: " + student.getId());
    System.out.println("student 中的 name 值為: " + student.getName());
    return "請求成功";
}

當我們這樣寫之後,Spring Boot 到時候就會將 request body 中的 JSON 參數,自動轉換成我們自定義的 STudent class 了,因此我們後續就可以直接從 test2() 中的 student 參數,直接取得到前端所傳遞過來的 JSON 數據了!

寫上上述的程式之後,可以重新運行一下 Spring Boot 程式,讓這段程式生效。

運行成功之後回到 API Tester 上,接著在 Http method 中選擇 POST 請求,url 填上 http://localhost:8080/test2,並且在 request body 中填上下列的 JSON 參數,這樣就可以模擬前端的請求。

{
    "id": 123,
    "name": "Judy"
}

而當我們按下 Send 鍵之後,在右下角的 response body 中,就會出現 Spring Boot 所回傳的「請求成功」的訊息。

此時當我們回到 IntelliJ 上查看的話,在下方的 console 中,就會出現「student 中的 id 值為: 123」、「student 中的 name 值為: Judy」的字串。

所以這就表示,我們就成功的透過 @RequestBody,去接住前端放在 request body 中所傳遞的 JSON 參數了!所以大家以後就可以透過 @RequestBody,在 Spring Boot 中取得前端所傳遞的 JSON 參數了。

小結:@RequestBody 用法總結 #

綜合以上的介紹,我們也可以來對 @RequestBody 做個小總結。

@RequestBody 的用途,就是「接住放在 request body 中的參數」,所以當前端將 JSON 參數透過 request body 來傳遞時,就可以使用 @RequestBody 來處理。

而在使用 @RequestBody 時,重點是要自己創建「和 JSON 參數一一對應的 Java class」出來,只要創建好這個 Java class,後續 Spring Boot 就會自動將 JSON 參數轉換成該 Java 物件了,非常方便!

補充:不過在創建和 JSON 參數一一對應的 Java class 時,就是考驗大家對於 JSON 格式的熟悉程度了,如果對 JSON 不太熟悉的話,也可以回頭參考 Day 16 - 結構化的呈現數據 - JSON 格式介紹 的介紹。

總結 #

這篇文章我們先列出了 Spring Boot 中提供的四種取得前端參數的註解,並且詳細的介紹了前兩個註解 @RequestParam@RequestBody 的用法,介紹要如何透過 @ReqestParam 取得 url 後面的參數,以及要如何透過 @RequestBody 取得 request body 中的 JSON 數據,這兩個都是實務上非常常用的作法,建議大家一定要熟練掌握才行!

那麼下一篇文章,我們就會接著來介紹另外兩個取得前端參數的註解:@RequestHeader 以及 @PathVariable,那我們就下一篇文章見啦!

補充:本文是擷取自我開設的線上課程 Java 工程師必備!Spring Boot 零基礎入門 的內容,如果你想了解更多的 Spring Boot 的用法,歡迎參考課程簡介 (輸入折扣碼「HH202504KU」即可享 85 折優惠)。