路徑匹配
Servlet API 將完整的請求路徑暴露為 requestURI,並進一步將其細分為 contextPath、servletPath 和 pathInfo,其值取決於 Servlet 的對映方式。從這些輸入中,Spring MVC 需要確定用於對映處理程式的查詢路徑,該路徑應排除 contextPath 和任何 servletMapping 字首(如果適用)。
servletPath 和 pathInfo 被解碼,這使得它們無法直接與完整的 requestURI 進行比較以派生查詢路徑,因此有必要對 requestURI 進行解碼。然而,這引入了它自身的問題,因為路徑可能包含編碼的保留字元,例如 "/" 或 ";",這些字元在解碼後可能會改變路徑的結構,這也會導致安全問題。此外,Servlet 容器可能會對 servletPath 進行不同程度的規範化,這使得對 requestURI 執行 startsWith 比較變得更加不可能。
這就是為什麼最好避免依賴帶有基於字首的 servletPath 對映型別的 servletPath。如果 DispatcherServlet 被對映為預設的 Servlet 且帶有 "/" 或沒有字首且帶有 "/*",並且 Servlet 容器是 4.0+,那麼 Spring MVC 能夠檢測 Servlet 對映型別並完全避免使用 servletPath 和 pathInfo。在 3.1 Servlet 容器上,假設相同的 Servlet 對映型別,可以透過在 MVC 配置中透過 路徑匹配 提供一個帶有 alwaysUseFullPath=true 的 UrlPathHelper 來實現等效功能。
幸運的是,預設的 Servlet 對映 "/" 是一個不錯的選擇。然而,仍然存在一個問題,即 requestURI 需要解碼才能與控制器對映進行比較。這再次是不希望的,因為有可能解碼保留字元,從而改變路徑結構。如果此類字元不在預期範圍內,您可以拒絕它們(例如 Spring Security HTTP 防火牆),或者您可以將 UrlPathHelper 配置為 urlDecode=false,但控制器對映將需要與編碼路徑匹配,這可能並非總是有效。此外,有時 DispatcherServlet 需要與另一個 Servlet 共享 URL 空間,並且可能需要按字首對映。
當使用 PathPatternParser 和解析模式時,上述問題得到了解決,這是使用 AntPathMatcher 進行字串路徑匹配的替代方案。PathPatternParser 從 Spring MVC 5.3 版本開始可用於 Spring MVC,並從 6.0 版本開始預設啟用。與需要解碼查詢路徑或編碼控制器對映的 AntPathMatcher 不同,解析後的 PathPattern 會一次一個路徑段地匹配路徑的解析表示形式(稱為 RequestPath)。這允許單獨解碼和清理路徑段值,而不會有改變路徑結構的風險。解析後的 PathPattern 還支援使用 servletPath 字首對映,只要使用了 Servlet 路徑對映並且字首保持簡單,即不包含編碼字元。有關模式語法詳細資訊和比較,請參見 模式比較。