路径匹配

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

servletPathpathInfo是解码的,这使得它们不可能直接与完整的requestURI进行比较以导出lookupPath,因此需要解码requestURI。但是,这会带来自身的问题,因为路径可能包含编码的保留字符,例如"/"";",这些字符解码后可能会改变路径的结构,也可能导致安全问题。此外,Servlet容器可能会对servletPath进行不同程度的规范化,这使得进一步无法对requestURI执行startsWith比较。

这就是最好避免依赖于基于前缀的servletPath映射类型的servletPath的原因。如果DispatcherServlet映射为默认Servlet(使用"/")或其他没有前缀的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的字符串路径匹配的替代方法)解决了上述问题。从5.3版本开始,Spring MVC可以使用PathPatternParser,从6.0版本开始默认启用。与需要解码查找路径或编码控制器映射的AntPathMatcher不同,解析的PathPattern一次一个路径段地与路径的解析表示(称为RequestPath)匹配。这允许单独解码和清理路径段值,而不会改变路径结构的风险。解析的PathPattern还支持使用servletPath前缀映射,只要使用Servlet路径映射并且前缀保持简单,即它没有编码字符。有关模式语法详细信息和比较,请参见模式比较