路徑比對

Servlet API 將完整請求路徑公開為 requestURI,並進一步將其細分為 contextPathservletPathpathInfo,這些值會根據 Servlet 的對應方式而有所不同。Spring MVC 需要從這些輸入中,判斷用於對應處理常式的查找路徑,該路徑應排除 contextPath 和任何 servletMapping 前綴(如果適用)。

servletPathpathInfo 已解碼,這使得它們無法直接與完整的 requestURI 進行比較,以推導出 lookupPath,因此有必要解碼 requestURI。然而,這也帶來了自身的問題,因為路徑可能包含編碼的保留字元,例如 "/"";",這些字元在解碼後可能會改變路徑的結構,進而導致安全性問題。此外,Servlet 容器可能會對 servletPath 進行不同程度的正規化,這使得更不可能針對 requestURI 執行 startsWith 比較。

這就是為什麼最好避免依賴 servletPath,它帶有基於前綴的 servletPath 對應類型。如果 DispatcherServlet 對應為預設 Servlet (使用 "/") 或以其他方式對應為沒有前綴 (使用 "/*"),且 Servlet 容器為 4.0+,則 Spring MVC 能夠偵測 Servlet 對應類型,並完全避免使用 servletPathpathInfo。在 3.1 Servlet 容器上,假設相同的 Servlet 對應類型,則可以透過在 MVC 組態的路徑比對中提供 alwaysUseFullPath=trueUrlPathHelper 來達到相同的效果。

幸運的是,預設 Servlet 對應 "/" 是一個不錯的選擇。然而,仍然存在一個問題,即需要解碼 requestURI,才能與控制器對應進行比較。再次強調,由於可能解碼會改變路徑結構的保留字元,因此這是不理想的。如果預期不會出現此類字元,則您可以拒絕它們(例如 Spring Security HTTP 防火牆),或者您可以將 UrlPathHelper 組態為 urlDecode=false,但控制器對應將需要與編碼的路徑進行比對,這可能並非總是有效。此外,有時 DispatcherServlet 需要與另一個 Servlet 共用 URL 空間,並且可能需要按前綴進行對應。

當使用 PathPatternParser 和已解析的模式時,這些上述問題得以解決,作為使用 AntPathMatcher 進行字串路徑比對的替代方案。PathPatternParser 從 Spring MVC 5.3 版開始可用,並從 6.0 版開始預設啟用。與 AntPathMatcher 需要解碼查找路徑或編碼控制器對應不同,已解析的 PathPattern 會與路徑的已解析表示形式(稱為 RequestPath)一次比對一個路徑段。這允許單獨解碼和清理路徑段值,而不會有改變路徑結構的風險。已解析的 PathPattern 也支援使用 servletPath 前綴對應,只要使用 Servlet 路徑對應且前綴保持簡單,即沒有編碼字元。有關模式語法詳細資訊和比較,請參閱模式比較