1. 概述
本快速教程將探討 Spring 框架中的 <em @PathVariable</em> 註解。
簡單來説,<em @PathVariable</em> 註解可用於處理請求 URI 映射中的模板變量,並將它們設置為方法參數。
讓我們看看如何使用 <em @PathVariable</em> 及其各種屬性。
2. 一個簡單的映射
一個簡單的用例是使用 @PathVariable 註解的端點,該端點識別具有主鍵的實體:
@GetMapping("/api/employees/{id}")
@ResponseBody
public String getEmployeesById(@PathVariable String id) {
return "ID: " + id;
}在本示例中,我們使用 @PathVariable 註解來提取 URI 中的模板部分,該部分由變量 {id} 表示。
一個簡單的 GET 請求 到 /api/employees/{id} 將會調用 getEmployeesById,並傳入提取的 id 值:
http://localhost:8080/api/employees/111
----
ID: 111現在讓我們更深入地探討這個標註,並查看其屬性。
3. 指定路徑變量名
在之前的示例中,由於方法參數名稱和路徑變量名稱相同,我們省略了定義路徑變量名稱。
但是,如果路徑變量名稱不同,可以在 @PathVariable 註解的參數中指定它。
@GetMapping("/api/employeeswithvariable/{id}")
@ResponseBody
public String getEmployeesByIdWithVariableName(@PathVariable("id") String employeeId) {
return "ID: " + employeeId;
}http://localhost:8080/api/employeeswithvariable/1
----
ID: 1我們還可以將路徑變量名定義為 @PathVariable(value=”id”),而不是 PathVariable(“id”) ,以提高可讀性。
4. 單個請求中的多個路徑變量
根據用例,我們可以在請求 URI 中擁有多個路徑變量,用於一個控制器方法,該方法同時具有多個方法參數:
@GetMapping("/api/employees/{id}/{name}")
@ResponseBody
public String getEmployeesByIdAndName(@PathVariable String id, @PathVariable String name) {
return "ID: " + id + ", name: " + name;
}http://localhost:8080/api/employees/1/bar
----
ID: 1, name: bar我們還可以使用方法參數類型為 java.util.Map<String, String> 處理多個 @PathVariable 參數:
@GetMapping("/api/employeeswithmapvariable/{id}/{name}")
@ResponseBody
public String getEmployeesByIdAndNameWithMapVariable(@PathVariable Map<String, String> pathVarsMap) {
String id = pathVarsMap.get("id");
String name = pathVarsMap.get("name");
if (id != null && name != null) {
return "ID: " + id + ", name: " + name;
} else {
return "Missing Parameters";
}
}http://localhost:8080/api/employees/1/bar
----
ID: 1, name: bar然而,在處理多個 @PathVariable 參數時,如果路徑變量字符串包含點(.)字符,存在一個小問題。我們之前已經詳細討論過這些特殊情況。
5. 可選路徑變量
在 Spring 中,帶有 @PathVariable 註解的方法參數默認是必需的:
@GetMapping(value = { "/api/employeeswithrequired", "/api/employeeswithrequired/{id}" })
@ResponseBody
public String getEmployeesByIdWithRequired(@PathVariable String id) {
return "ID: " + id;
}鑑於其外觀,上述控制器應同時處理 /api/employeeswithrequired 和 /api/employeeswithrequired/1 請求路徑。然而,由於默認情況下使用 @PathVariables 註解的參數是強制性的,因此它無法處理髮送到 /api/employeeswithrequired 路徑的請求。
http://localhost:8080/api/employeeswithrequired ---- {"timestamp":"2020-07-08T02:20:07.349+00:00","status":404,"error":"Not Found","message":"","path":"/api/employeeswithrequired"}http://localhost:8080/api/employeeswithrequired/1 ---- ID: 111
我們可以用兩種不同的方式來處理這個問題。
5.1. 設置 @PathVariable 為非必需
我們可以將 @PathVariable 的 required 屬性設置為 false,使其成為可選的。 這樣,我們就可以處理帶有和不帶路徑變量的 URI 版本:
@GetMapping(value = { "/api/employeeswithrequiredfalse", "/api/employeeswithrequiredfalse/{id}" })
@ResponseBody
public String getEmployeesByIdWithRequiredFalse(@PathVariable(required = false) String id) {
if (id != null) {
return "ID: " + id;
} else {
return "ID missing";
}
}http://localhost:8080/api/employeeswithrequiredfalse
----
ID missing5.2. 使用 <em>java.util.Optional</em>
自 Spring 4.1 引入以來,我們還可以使用 <em>java.util.Optional<T></em> (Java 8 及更高版本可用) 來處理非必選路徑變量:
@GetMapping(value = { "/api/employeeswithoptional", "/api/employeeswithoptional/{id}" })
@ResponseBody
public String getEmployeesByIdWithOptional(@PathVariable Optional<String> id) {
if (id.isPresent()) {
return "ID: " + id.get();
} else {
return "ID missing";
}
}如果未指定路徑變量 id, 我們將獲得默認響應:
http://localhost:8080/api/employeeswithoptional
----
ID missing 5.3. 使用類型為 Map<String, String> 的方法參數
如前所述,我們可以使用單個方法參數,類型為 java.util.Map,來處理請求 URI 中的所有路徑變量。 我們也可以使用這種策略來處理可選路徑變量的情況:
@GetMapping(value = { "/api/employeeswithmap/{id}", "/api/employeeswithmap" })
@ResponseBody
public String getEmployeesByIdWithMap(@PathVariable Map<String, String> pathVarsMap) {
String id = pathVarsMap.get("id");
if (id != null) {
return "ID: " + id;
} else {
return "ID missing";
}
}6. @PathVariable 的默認值
默認情況下,沒有提供定義方法參數(註解為 @PathVariable)默認值的機制。但是,我們可以採用之前討論的相同策略來滿足 @PathVariable 的默認值需求,只需檢查路徑變量是否為 null。
例如,使用 java.util.Optional<String, String>,我們可以判斷路徑變量是否為 null。如果為 null,則可以直接用默認值響應請求:
@GetMapping(value = { "/api/defaultemployeeswithoptional", "/api/defaultemployeeswithoptional/{id}" })
@ResponseBody
public String getDefaultEmployeesByIdWithOptional(@PathVariable Optional<String> id) {
if (id.isPresent()) {
return "ID: " + id.get();
} else {
return "ID: Default Employee";
}
}7. 結論
在本文中,我們探討了如何使用 Spring 的 <em @PathVariable</em> 註解。我們還識別瞭如何有效地使用 <em @PathVariable</em> 註解,以適應不同的用例,例如可選參數和處理默認值。