loading table of contents...

4.3.1.6. Path Matching Details

The Spring documentation (http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping) describes in detail the request matching features provided by @RequestMapping. An important, if not the most important request matching criterion, is matching the request URI path against the URI templates defined by @RequestMapping annotations, a process performed by a PathMatcher implementation. There are two differences between Spring's default AntPathMatcher implementation and the UriTemplatePathMatcher provided by the CAE:

  • @RequestMapping supports the use of regular expressions in URI template variables, specified as {variable:regex}. An URL path will only be considered a match, if all the extracted URI template variable values match the corresponding regular expressions. If no regular expression is specified for a variable, the default is "[^/]+?", that is, any non-empty sequence of any characters except a slash '/'. In other words, by default, a variable can match only one non-empty URI path segment. For instance, the URI template /{segment} would match the URI path /home, but not /news/breaking.

    If the regular expression allows for a slash character '/', the CAE path matcher implementation can match multiple path segments for a single variable. This would not be possible with Spring's default path matcher. For instance, the URI template /{segments:.+}/index.html would match the URI path /one/two/index.html, with variable segment bound to "one/two". As a convenience and to simplify handler method implementations, an @PathVariable handler method argument representing a template variable can be of type List<String>. In this case, the variable value will be split into a list of path segments separated by slash characters '/'. In the previous example, the list ["one", "two"] would be passed to the handler method.

  • UriTemplatePathMatcher does not support Ant-style globs: *, **, and ?. These characters should not be used in the literal part of URI templates, but only in regular expressions associated with template variables. Outside a template variable definition, they will be interpreted literally.

URI path matching behavior is not only influenced by @RequestMapping annotations, but also by some global Spring configuration parameters:

  • RequestMappingHandlerMapping.useTrailingSlashMatch is true by default and causes any URI path with a trailing slash to be a match for a given URI template, if the template does not end with a slash, and the URI path without the slash would be a match. In effect, URIs will typically match a template, if they have a trailing slash, even if the template does not have a trailing slash. For instance, the URI template /{segment} will match both /home and /home/.

  • RequestMappingHandlerMapping.useSuffixPatternMatch is true by default and causes any URI path with an extra .* suffix (dot, plus some characters) to match a template, if the template does not contain any '.' characters. In effect, the URI path matching process will typically ignore extra path suffixes, if the template does not contain any dot characters. For instance, the URI template /{segment}/index will match both /home/index and /home/index.html.

  • UrlPathHelper.urlDecode is true by default and causes request URI paths to be percent decoded according to RFC 3986, before they are matched against any URI template. This is usually the desired behavior and should not be changed as it relieves the application developer from taking into consideration percent encoding when defining URI templates. Any template variable regular expressions should therefore match the decoded form of reserved characters, if such characters are to be allowed in variable values. For instance, the URI template /products/{name:[a-zäöü]+} will match the request URI path /products/m%C3%A4use (assuming a request character encoding of UTF-8, see below). Note that the percent character '%' is not a valid name character as defined by the URI template. The matching process operates on the decoded URI path /products/mäuse.

    As a consequence of this behavior, an application cannot differentiate during matching, whether the client sent a character percent encoded or not. Due to this ambiguity, an application should not generate URLs with path segments containing (percent encoded) slash characters '/'. Even though such URLs are valid and can be generated, the matching process acting on the decoded path would treat such path segment as multiple segments. URLs with path segments containing encoded slash characters are considered unsound and should be avoided. Given the same example URI template as above, if the link scheme expanded the URI template with a name value of "tablets/laptops", this would result in the valid URI path /products/tablets%2Flaptops. However, when dispatching a request for this path, it would be decoded and matched against URI templates as /products/tablets/laptops, and the template /products/{name:[a-zäöü]+} would not match.

  • When percent decoding the request URI path, UrlPathHelper uses the request encoding (HttpServletRequest#getCharacterEncoding) or defaults to ISO-8859-1, if no request character encoding is available. Since this default character encoding is different from the UriComponents default encoding (UTF-8) during URL generation, it is recommended to force there request character encoding to UTF-8 by configuring an org.springframework.web.filter.CharacterEncodingFilter in the application's web.xml, with encoding=UTF-8 and forceEncoding=true:

    <filter>
      <filter-name>Character Encoding Filter</filter-name>
      <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter
      </filter-class>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
      </init-param>
    </filter>