1. 概述
在本教程中,我們將學習如何在 Spring 中使路徑變量成為可選的。首先,我們將描述 Spring 如何綁定 @PathVariable 參數到處理方法中。然後,我們將展示在不同 Spring 版本中使路徑變量成為可選的各種方法。
對於路徑變量的快速概述,請閲讀我們的 Spring MVC 文章。
2. 如何綁定 @PathVariable 參數
Spring 默認情況下,它會嘗試將帶有 @PathVariable 註解的參數綁定到處理方法中的相應 URI 模板變量。如果 Spring 失敗,則不會將請求傳遞到該處理方法。
例如,考慮以下 getArticle 方法,它嘗試(未成功)使 id 路徑變量成為可選的:
@RequestMapping(value = {"/article/{id}"})
public Article getArticle(@PathVariable(name = "id") Integer articleId) {
if (articleId != null) {
//...
} else {
//...
}
}在此,getArticle方法旨在處理對/article和/article/{id}的請求。Spring會嘗試將articleId參數綁定到id路徑變量,如果存在的話。
例如,向/article/123發送請求會將articleId的值設置為123。
另一方面,如果我們向/article發送請求,Spring會因為以下異常返回狀態碼500:
org.springframework.web.bind.MissingPathVariableException:
Missing URI template variable 'id' for method parameter of type Integer這是因為 Spring 無法為 articleId 參數設置值,因為 id 缺少時值。
因此,我們需要某種方法來告知 Spring 如果某個 @PathVariable 參數沒有對應的路徑變量,則忽略綁定,正如後續章節所展示的。
3. 使路徑變量可選
This section describes how to make path variables optional, allowing your application to function without them when they are not provided. This is particularly useful when dealing with legacy systems or situations where path variables are not always available.
To achieve this, you can use the optional() method on the Path object. This method returns a new Path object that will only use the path variable if it is provided. If the path variable is not provided, the Path object will use the default path.
Here's an example:
const path = new Path("path/to/file");
// Using the Path object with a path variable
const pathWithVariable = new Path("path/to/file", { variable: "myVariable" });
// Using the Path object without a path variable
const pathWithoutVariable = new Path("path/to/file");
In the first example, the Path object is created with a path variable. In the second example, the Path object is created without a path variable. The optional() method ensures that the Path object will use the default path if the path variable is not provided.
3.1. 使用 required 屬性的 @PathVariable 註解
自 Spring 4.3.3 版本起,@PathVariable 註解定義了 required 布爾屬性,用於指示路徑變量是否必須傳遞給處理方法。
例如,以下版本的 getArticle 使用了 required 屬性:
@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable(required = false) Integer articleId) {
if (articleId != null) {
//...
} else {
//...
}
}由於 required 屬性設置為 false,Spring 在請求中未發送 id 路徑變量時不會報錯。換句話説,Spring 如果收到該變量,會將 articleId 設置為 id,否則設置為 null。
另一方面,如果 required 設置為 true,則當 id 缺失時,Spring 會拋出異常。
3.2. 使用可選參數類型
以下實現展示了 Spring 4.1 以及 JDK 8 的 Optional 類如何提供另一種使 articleId 為可選的方式:
@RequestMapping(value = {"/article", "/article/{id}"}")
public Article getArticle(@PathVariable Optional<Integer> optionalArticleId) {
if (optionalArticleId.isPresent()) {
Integer articleId = optionalArticleId.get();
//...
} else {
//...
}
}在這裏,Spring 創建了 Optional<Integer> 實例,optionalArticleId,用於存儲 id 的值。如果 id 存在,optionalArticleId 將包裝其值,否則,optionalArticleId 將包裝一個 null 值。然後,我們可以使用 Optional 的 isPresent(), get(), 或 orElse() 方法來處理該值。
3.3. 使用 Map 參數類型
自 Spring 3.2 版本起,使用 Map 類型定義可選路徑變量的另一種方式是使用 @PathVariable 參數,其中參數類型為 Map。
@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable Map<String, String> pathVarsMap) {
String articleId = pathVarsMap.get("id");
if (articleId != null) {
Integer articleIdAsInt = Integer.valueOf(articleId);
//...
} else {
//...
}
}在本示例中,Map<String, String> 類型的 pathVarsMap 參數收集了 URI 中的所有路徑變量,以鍵值對的形式存儲。然後,我們可以使用 get() 方法獲取特定的路徑變量。
請注意,由於 Spring 將路徑變量的值提取為 String 類型,因此我們使用了 Integer.valueOf() 方法將其轉換為 Integer 類型。
3.4. 使用兩個處理器方法
如果我們在使用舊版本的 Spring,我們可以將 getArticle 處理方法拆分為兩個方法。
第一種方法將處理對 /article/{id} 的請求:
@RequestMapping(value = "/article/{id}")
public Article getArticle(@PathVariable(name = "id") Integer articleId) {
//...
}
雖然第二種方法將處理對 /article 的請求:
@RequestMapping(value = "/article")
public Article getDefaultArticle() {
//...
}4. 結論
總結一下,我們討論瞭如何在不同版本的 Spring 中使路徑變量成為可選的。