1. 概述
在本簡短教程中,我們將討論在 Spring MVC 中常見的問題——當使用 Spring 的 <em @PathVariable 與 <em @RequestMapping 結合,用於映射請求 URI 末尾包含點時,我們會在變量中得到不完整的值,該值在最後一個點處被截斷。
在下一部分,我們將重點討論原因以及如何更改此行為。
有關 Spring MVC 的介紹,請參閲本文。
2. 不希望的 Spring 幫助
該框架由於其對路徑變量的解釋方式,導致這種通常不希望出現的行為。
具體來説,Spring 認為任何路徑中最後一個點之後的內容都屬於文件擴展名,例如 .json 或 .xml。
因此,它會截斷值以檢索參數。
讓我們通過一個使用路徑變量的示例來演示,然後分析不同可能值的結果:
@RestController
public class CustomController {
@GetMapping("/example/{firstValue}/{secondValue}")
public void example(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
// ...
}
}通過以上示例,讓我們考慮後續請求並評估我們的變量:
- 使用 URL example/gallery/link 會導致變量 firstValue = “gallery” 和 secondValue = “link”
- 使用 URL example/gallery.df/link.ar 時,我們將有 firstValue = “gallery.df” 和 secondValue = “link”
- 使用 URL example/gallery.df/link.com.ar 時,我們的變量將為: firstValue = “gallery.df” 和 secondValue = “link.com”
如我們所見,第一個變量不受影響,但第二個變量始終會被截斷。
3. 解決方案
一種解決此問題的辦法是修改我們的 @PathVariable 定義,通過添加正則表達式映射。 這樣,包括最後一個的任何點都將被視為參數的一部分。
@GetMapping("/example/{firstValue}/{secondValue:.+}")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}為了避免這個問題,一種方法是在我們的 @PathVariable 的末尾添加斜槓。 這將包含我們的第二個變量,從而保護它免受 Spring 的默認行為的影響:
@GetMapping("/example/{firstValue}/{secondValue}/")上述兩種解決方案適用於我們正在修改的單個請求映射。
如果我們要改變 MVC 級別的全局行為,則需要提供自定義配置。為此,我們可以擴展 WebMvcConfigurationSupport 並覆蓋其 getPathMatchConfigurer() 方法以調整 PathMatchConfigurer。
@Configuration
public class CustomWebMvcConfigurationSupport extends WebMvcConfigurationSupport {
@Override
protected PathMatchConfigurer getPathMatchConfigurer() {
PathMatchConfigurer pathMatchConfigurer = super.getPathMatchConfigurer();
pathMatchConfigurer.setUseSuffixPatternMatch(false);
return pathMatchConfigurer;
}
}我們必須記住,這種方法會影響所有 URL。
通過這三個選項,我們將會獲得相同的結果:當調用 example/gallery.df/link.com.ar URL 時,我們的 secondValue 變量將被評估為 “link.com.ar”,這是我們想要的結果。
3.1. 棄用通知
自 Spring Framework 5.2.4 版本起,setUseSuffixPatternMatch(boolean) 方法已被棄用,以阻止使用路徑擴展進行請求路由和內容協商。 實際上,當前實現使得 Web 應用程序難以防禦 反射式文件下載 (RFD) 攻擊。
此外,自 Spring Framework 5.3 版本起,後綴模式匹配僅適用於顯式註冊的後綴,以防止任意擴展。
總而言之,自 Spring 5.3 版本起,我們無需使用 setUseSuffixPatternMatch(false),因為它默認已禁用。
4. 結論
在本文檔中,我們探討了在 Spring MVC 中使用 @PathVariable 和 @RequestMapping 時解決常見問題的不同方法,以及導致該問題的原因。