iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
Software Development

spring boot 3 學習筆記系列 第 20

Day20 - Spring Boot Web 篇:接收來自 URL 的動態參數

  • 分享至 

  • xImage
  •  

Day19,我們學會了如何建立一個回傳固定訊息 "Hello, World!" 的 API 端點 (Endpoint)。但真實世界的應用程式需要更靈活,它必須能夠根據使用者提供的不同資訊,來回傳不同的結果。

今天,我們就要來學習如何讓 API「動起來」,接收來自 URL 的動態參數。

學習目標

完成本單元後,你將能夠:

  1. 理解兩種在 URL 中傳遞資料的核心方式:路徑變數 (Path Variable)查詢參數 (Query Parameter)
  2. 熟練運用 @PathVariable 從 URL 路徑中 (如 /users/123) 提取變數,用來指定特定資源。
  3. 熟練運用 @RequestParam 從 URL 查詢字串中 (如 /search?keyword=java) 提取參數,用來做資料的篩選、排序。
  4. 親手寫出如「查詢特定 ID 的使用者」、「根據關鍵字搜尋商品」等更實用的 API。

第一站:@PathVariable - 擷取 URL 路徑中的變數

什麼是 @PathVariable

想像一下,你在設計一個查詢使用者資料的 API (Application Programming Interface)。你希望 URL (Uniform Resource Locator) 的結構是這樣的:

  • /users/1:查詢 ID 為 1 的使用者
  • /users/42:查詢 ID 為 42 的使用者
  • /products/apple:查詢名稱為 "apple" 的商品

你會發現,URL 中的 142apple 都是變數。我們不可能為世界上每一個 ID 都手動寫一個 @GetMapping。這時,@PathVariable 就登場了!

@PathVariable 的核心功能就是將 URL 路徑中的變數值,綁定 (Bind) 到你控制器 (Controller) 方法中的參數上。它讓我們可以建立這種動態、有彈性的 URL 結構。

簡單來說: @PathVariable 就像一個模板取值工具,它能從 URL 的特定位置「挖」出一個值,並將其作為變數傳遞給你的 Java 程式碼。

如何使用 @PathVariable

使用 @PathVariable 非常直觀,只需要兩步驟:

  1. 在路徑中用大括號 {} 定義變數:在 @GetMapping 或其他請求註解 (Annotation) 的路徑中,使用 {變數名} 來宣告一個位置是動態的。
  2. 在方法參數中用 @PathVariable 接收:在處理該請求的方法中,使用 @PathVariable 註解 (Annotation) 來告訴 Spring:「請把 URL 路徑上對應的值給我」。

範例 1:查詢特定 ID 的使用者

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users") // 將 /users 作為這個 Controller 的共同前綴
public class UserController {

    // 1. 在路徑中定義變數 {id}
    @GetMapping("/{id}")
    // 2. 使用 @PathVariable 將 {id} 的值綁定到 Long id 參數上
    public String getUserById(@PathVariable Long id) {
        // 為了簡化,我們直接返回一個字串,實務上這裡會是查詢資料庫的邏輯
        return "正在查詢 ID 為 " + id + " 的使用者資料...";
    }
}

解析:

  • @GetMapping("/{id}"):這裡的 {id} 就是我們定義的路徑變數。它告訴 Spring,URL 在 /users/ 後面的那段內容是一個動態變數,我們把它命名為 id
  • @PathVariable Long id@PathVariable 會自動去路徑中尋找同名的變數 ({id}),並將其值賦予給方法參數 id。Spring Boot 非常聰明,它還會自動幫你將 URL 中的字串 (例如 "123") 轉換成你指定的型別 (例如 Long)。

啟動程式並測試:

  • 訪問 http://localhost:8080/users/1 => 回應: 正在查詢 ID 為 1 的使用者資料...
  • 訪問 http://localhost:8080/users/99 => 回應: 正在查詢 ID 為 99 的使用者資料...

範例 2:當變數名稱不一致時

雖然不建議,但有時路徑變數名稱可能和你的方法參數名稱不同。@PathVariable 允許你明確指定要綁定哪個變數。

@GetMapping("/profile/{userId}")
public String getUserProfile(@PathVariable("userId") Long id) {
    // 透過 @PathVariable("userId"),明確告訴 Spring
    // 將路徑中的 {userId} 變數,賦值給名為 id 的參數
    return "查詢使用者 ID 為 " + id + " 的個人資料。";
}

最佳實踐 (Best Practice): 為了程式碼的簡潔與可讀性,強烈建議保持路徑變數和方法參數名稱的一致性,這樣就可以省略 ("userId"),讓程式碼更乾淨。

範例 3:可選的 @PathVariable (進階)

有時候,我們希望某個路徑變數是可選的,例如 /search/search/keyword 都能對應到同一個方法。

重要提示:要讓 @PathVariable 可選,你必須提供兩個路徑映射:一個包含變數,另一個不包含。

import java.util.Optional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SearchController {

    // 使用 Java 8 的 Optional<T> 是處理可選參數的現代且安全作法
    // 1. 提供兩種路徑
    @GetMapping({"/find", "/find/{query}"})
    // 2. 將 required 設為 false,並用 Optional 包裝
    public String findItems(@PathVariable(name = "query", required = false) Optional<String> query) {
        if (query.isPresent()) {
            return "使用 Optional 查找: " + query.get();
        } else {
            return "使用 Optional 查找所有項目...";
        }
    }
}
  • Optional<String> 的好處:它能清晰地表達「這個參數可能不存在」的意圖,並幫助你避免惱人的空指針異常 (NullPointerException)。

第二站:@RequestParam - 解析 URL 查詢參數

什麼是 @RequestParam

當你在 Google 搜尋時,網址會變成像這樣: https://www.google.com/search?q=Spring+Boot

網址中 ? 後面的部分,如 q=Spring+Boot,就是查詢參數 (Query Parameter)。它是一種 key=value 形式的組合,用來傳遞額外資訊,常見於篩選、排序、分頁等功能。

在 Spring Boot 中,@RequestParam 的工作就是將這些 URL 中的查詢參數,綁定到你控制器方法中的參數上

簡單來說: @RequestParam 就像一個鉤子,幫你把 URL 在 ? 後面的資料,輕鬆地「鉤」到你的 Java 程式碼裡。

如何使用 @RequestParam

範例 1:簡單的問候 API

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    @GetMapping("/greeting")
    public String greet(@RequestParam String name) {
        return "哈囉, " + name + "!歡迎學習 Spring Boot!";
    }
}
  • @RequestParam String name:這行程式碼告訴 Spring:「請幫我從 URL 中找到一個叫做 name 的查詢參數,並把它的值放進 String name 這個變數裡。」

啟動程式並測試:

  • 訪問 http://localhost:8080/greeting?name=John => 回應: 哈囉, John!歡迎學習 Spring Boot!

@RequestParam 的常用屬性

@RequestParam 提供了一些非常有用的屬性,讓我們的 API 更有彈性。

  • name (或 value):當 URL 參數名和 Java 變數名不同時使用。
// URL 需使用 ...?username=Mary
@GetMapping("/greet-user")
public String greetUser(@RequestParam(name = "username") String name) {
    return "Hi, " + name;
}
  • required:設定參數是否為必需的,預設為 true
// URL 可以不帶 name 參數
@GetMapping("/greet-optional")
public String greetOptional(@RequestParam(required = false) String name) {
    if (name == null) {
        return "哈囉, 陌生人!";
    }
    return "哈囉, " + name + "!";
}

測試:訪問 http://localhost:8080/greet-optional => 回應: 哈囉, 陌生人!

  • defaultValue:提供預設值。當你設定了 defaultValuerequired 會自動變為 false
// 如果 URL 不帶 name 參數,name 變數的值會是 "訪客"
@GetMapping("/greet-default")
public String greetDefault(@RequestParam(defaultValue = "訪客") String name) {
    return "哈囉, " + name + "!歡迎光臨!";
}

測試:訪問 http://localhost:8080/greet-default => 回應: 哈囉, 訪客!歡迎光臨!

@PathVariable vs. @RequestParam:何時該用誰?

這是一個非常重要的觀念,也是初學者常混淆的地方。

特性 @PathVariable (路徑變數) @RequestParam (查詢參數)
用途 識別一個特定的「資源 (Resource)」 對資源進行「篩選、排序或分頁」
URL 結構 乾淨、有階層性,是 URL 路徑的一部分 ? 之後,以 key=value 形式存在
語意 "我要這個東西" "我要符合這些條件的東西"
範例 /users/123 (取得 ID 為 123 的使用者) /products?category=books&page=1 (取得書籍類的第一頁商品)
範例 /orders/ORD-001 (取得訂單號 ORD-001) /users?status=active&sort=name_asc (取得所有活躍使用者,並依姓名升序排序)
是否可選 通常是必需的 (因為它指定了資源) 可選的居多 (篩選條件可有可無)

恭喜你!現在你已經掌握了讓 API 變得動態的兩大利器。你不再只能建立回傳固定內容的 API,而是可以:

  • 透過 @PathVariable 建立一個 GET /users/{id} 的端點來查詢特定使用者。
  • 透過 @RequestParam 建立一個 GET /products 的端點,並用 ?keyword=laptop 來搜尋商品,或用 ?sort=price 來排序。

這些是建構真實世界 RESTful API 的基礎,你已經為後續更複雜的功能打下了堅實的根基!

相關資料來源


上一篇
Day19 - Spring Boot Web 篇:建立你的第一個 API 端點
系列文
spring boot 3 學習筆記20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言