路径匹配

Servlet API 将完整的请求路径暴露为 requestURI,并进一步将其细分为 contextPathservletPathpathInfo,其值取决于 Servlet 的映射方式。从这些输入中,Spring MVC 需要确定用于映射处理程序的查找路径,该路径应排除 contextPath 和任何 servletMapping 前缀(如果适用)。

servletPathpathInfo 被解码,这使得它们无法直接与完整的 requestURI 进行比较以派生查找路径,因此有必要对 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 版本开始可用于 Spring MVC,并从 6.0 版本开始默认启用。与需要解码查找路径或编码控制器映射的 AntPathMatcher 不同,解析后的 PathPattern 会一次一个路径段地匹配路径的解析表示形式(称为 RequestPath)。这允许单独解码和清理路径段值,而不会有改变路径结构的风险。解析后的 PathPattern 还支持使用 servletPath 前缀映射,只要使用了 Servlet 路径映射并且前缀保持简单,即不包含编码字符。有关模式语法详细信息和比较,请参见 模式比较

© . This site is unofficial and not affiliated with VMware.