|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
路径匹配
Servlet API 将完整请求路径公开为 requestURI,并进一步将其细分为 contextPath、servletPath 和 pathInfo,这些值会根据 Servlet 的映射方式而变化。基于这些输入,Spring MVC 需要确定用于映射处理器的查找路径,该路径应排除 contextPath 以及适用的 servletMapping 前缀(如果适用)。
servletPath 和 pathInfo 会被解码,这使得它们无法直接与完整的 requestURI 进行比较,从而无法推导出 lookupPath,这使得解码 requestURI 变得必要。然而,这会引入其自身的问题,因为路径可能包含编码的保留字符,如 "/" 或 ";",这些字符在解码后可能会改变路径的结构,也可能导致安全问题。此外,Servlet 容器可能会以不同的程度对 servletPath 进行规范化,这进一步使得无法将 startsWith 与 requestURI 进行比较。
这就是为什么最好避免依赖带有前缀的servletPath映射类型所提供的servletPath。如果DispatcherServlet被映射为默认Servlet,使用"/"或通过"/*"没有前缀,并且Servlet容器是4.0+的话,Spring MVC能够检测到Servlet映射类型并完全避免使用servletPath和pathInfo。在3.1版的Servlet容器中,假设相同的Servlet映射类型,可以通过在MVC配置中通过路径匹配提供UrlPathHelper和alwaysUseFullPath=true来实现相同的效果。
幸运的是,默认的Servlet映射"/"是一个好的选择。然而,仍然存在一个问题,即需要对requestURI进行解码,以便可以与控制器映射进行比较。这再次是不希望的,因为可能会解码改变路径结构的保留字符。如果不需要这些字符,那么你可以拒绝它们(如Spring Security的HTTP防火墙),或者你可以用urlDecode=false配置UrlPathHelper,但控制器映射需要与编码后的路径匹配,这可能并不总是有效。此外,有时DispatcherServlet需要与其他Servlet共享URL空间,并可能需要通过前缀进行映射。
上述问题在使用PathPatternParser和解析模式时得到解决,这可以作为使用AntPathMatcher进行字符串路径匹配的替代方案。该PathPatternParser功能自Spring MVC 5.3版本起可用,并在6.0版本中默认启用。与需要解码查找路径或编码控制器映射的AntPathMatcher不同,解析后的PathPattern会匹配称为RequestPath的路径解析表示形式,每次一个路径段。这使得可以单独对路径段值进行解码和无害化处理,而无需担心改变路径结构。解析后的PathPattern还支持使用servletPath前缀映射,前提是使用Servlet路径映射且前缀保持简单(即不含编码字符)。有关模式语法详情及对比,请参阅
模式比较。