路径匹配

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

servletPathpathInfo已解码,这使它们无法直接与完整的requestURI进行比较,以便推导出查找路径,因此需要解码requestURI。然而,这会引入自己的问题,因为路径可能包含编码的保留字符,如"/"";",这些字符解码后可能会改变路径的结构,也可能导致安全问题。此外,Servlet容器可能会以不同程度对servletPath进行规范化,这使得无法对requestURI执行startsWith比较。

这就是为什么最好避免依赖基于前缀的servletPath映射类型。如果DispatcherServlet被映射为默认Servlet,使用"/"或者没有前缀使用"/*",并且Servlet容器为4.0+,那么Spring MVC能够检测到Servlet映射类型,并避免使用servletPathpathInfo。在3.1 Servlet容器上,假设相同的Servlet映射类型,可以通过在MVC配置中提供一个UrlPathHelper,使用alwaysUseFullPath=true来实现相同的效果,详情请参阅路径匹配

幸运的是,默认的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路径映射并且前缀保持简单,即没有编码字符。有关模式语法详细信息和比较,请参阅模式比较