The Servlet API exposes the full request path as requestURI and further splits it into contextPath, servletPath and pathInfo, the meanings of which depend on how the servlet is rendered. From this input, Spring MVC must determine the search path that will be used to map the handler, which is the path in the mapping of DispatcherServlet itself, excluding contextPath and any servletMapping prefix, if present.

ServletPath and pathInfo are decoded, making it impossible to directly compare them with the full requestURI to obtain the lookupPath, so decoding becomes necessary requestURI. However, this poses its own problems because the path may contain encoded reserved characters such as "/" or ";", which may change the structure of the path after they are decoded, which may also lead to security problems. Additionally, servlet containers may normalize servletPath to varying degrees, making it even more impossible to compare startsWith with requestURI.

This is why it is best to avoid depending on the servletPath that accompanies the prefix-based servletPath mapping type. If DispatcherServlet is rendered as a default servlet with a "/" sign, or otherwise rendered without a prefix with a "/*" sign, and the servlet container is versioned 4.0+, then Spring MVC will be able to determine the servlet's mapping type and completely avoid the use of servletPath and pathInfo. In a 3.1 servlet container, assuming the same servlet mapping types are used, a similar result can be achieved by providing UrlPathHelper with alwaysUseFullPath=true via Path Matching in the MVC configuration.

Fortunately, the default servlet mapping "/" is a smart choice. However, there is still the issue that requestURI needs to be decoded to be able to compare with controller mappings. This is again undesirable due to the possibility of decoding reserved characters which will change the path structure. If such characters are not expected, you can block them (as in the Spring Security HTTP firewall), or you can configure UrlPathHelper with urlDecode=false, but the controller mappings will need to match the encoded path, which doesn't always work acceptably. Moreover, sometimes DispatcherServlet has to share URL space with another servlet, and this may require mapping by prefix.

The above problems can be solved more thoroughly by moving from PathMatcher to the parsed PathPattern, available in version 5.3 and higher. Unlike AntPathMatcher, which requires either a decoded search path or an encoded controller mapping, a parsed PathPattern is matched to a parsed path representation called RequestPath, by one path segment at a time. This allows path segment values to be decoded and cleared individually without the risk of changing the path structure. A parsed PathPattern also supports the use of a servletPath prefix mapping, as long as the prefix is kept simple and does not contain characters that need to be encoded.