Update docs for PathPattern support in WebMvc

Closes gh-24945
This commit is contained in:
Rossen Stoyanchev 2020-06-18 21:16:21 +01:00
parent 2d5f9723fa
commit ce728a6c4b
2 changed files with 49 additions and 67 deletions

View File

@ -47,9 +47,12 @@ import org.springframework.util.StringUtils;
* and captures it as a variable named "spring"</li>
* </ul>
*
* Notable behavior difference with {@code AntPathMatcher}:<br>
* {@code **} and its capturing variant <code>{*spring}</code> cannot be used in the middle of a pattern
* string, only at the end: {@code /pages/{**}} is valid, but {@code /pages/{**}/details} is not.
* <p><strong>Note:</strong> In contrast to
* {@link org.springframework.util.AntPathMatcher}, {@code **} is supported only
* at the end of a pattern. For example {@code /pages/{**}} is valid but
* {@code /pages/{**}/details} is not. The same applies also to the capturing
* variant <code>{*spring}</code>. The aim is to eliminate ambiguity when
* comparing patterns for specificity.
*
* <h3>Examples</h3>
* <ul>

View File

@ -1529,40 +1529,39 @@ The following example has type and method level mappings:
==== URI patterns
[.small]#<<web-reactive.adoc#webflux-ann-requestmapping-uri-templates, WebFlux>>#
You can map requests by using glob patterns and wildcards:
`@RequestMapping` methods can be mapped using URL patterns. There are two alternatives:
[cols="2,3,5"]
|===
|Pattern |Description |Example
* `PathPattern` -- a pre-parsed pattern matched against the URL path also pre-parsed as
`PathContainer`. Designed for web use, this solution deals effectively with encoding and
path parameters, and matches efficiently.
* `AntPathMatcher` -- match String patterns against a String path. This is the original
solution also used in Spring configuration to select resources on the classpath, on the
filesystem, and other locations. It is less efficient and the String path input is a
challenge for dealing effectively with encoding and other issues with URLs.
| `+?+`
| Matches one character
| `+"/pages/t?st.html"+`
`PathPattern` is the recommended solution for web applications and it is the only choice in
Spring WebFlux. Prior to version 5.3, `AntPathMatcher` was the only choice in Spring MVC
and continues to be the default. However `PathPattern` can be enabled in the
<<mvc-config-path-matching, MVC config>>.
matches `+"/pages/test.html"+`
and `+"/pages/t3st.html"+`
`PathPattern` supports the same pattern syntax as `AntPathMatcher`. In addition it also
supports the capturing pattern, e.g. `+{*spring}+`, for matching 0 or more path segments
at the end of a path. `PathPattern` also restricts the use of `+**+` for matching multiple
path segments such that it's only allowed at the end of a pattern. This eliminates many
cases of ambiguity when choosing the best matching pattern for a given request.
For full pattern syntax please refer to
{api-spring-framework}/web/util/pattern/PathPattern.html[PathPattern] and
{api-spring-framework}/util/AntPathMatcher.html[AntPathMatcher].
| `+*+`
| Matches zero or more characters within a path segment
| `+"/resources/*.png"+` matches `+"/resources/file.png"+`
Some example patterns:
`+"/projects/*/versions"+` matches `+"/projects/spring/versions"+` but does not match `+"/projects/spring/boot/versions"+`
* `+"/resources/ima?e.png"+` - match one character in a path segment
* `+"/resources/*.png"+` - match zero or more characters in a path segment
* `+"/resources/**"+` - match multiple path segments
* `+"/projects/{project}/versions"+` - match a path segment and capture it as a variable
* `+"/projects/{project:[a-z]+}/versions"+` - match and capture a variable with a regex
| `+**+`
| Matches zero or more path segments until the end of the path
| `+"/resources/**"+` matches `+"/resources/file.png"+` and `+"/resources/images/file.png"+`
| `+{name}+`
| Matches a path segment and captures it as a variable named "name"
| `+"/projects/{project}/versions"+` matches `+"/projects/spring/versions"+` and captures `+project=spring+`
| `+{name:[a-z]+}+`
| Matches the regexp `+"[a-z]+"+` as a path variable named "name"
| `+"/projects/{project:[a-z]+}/versions"+` matches `+"/projects/spring/versions"+` but not `+"/projects/spring1/versions"+`
|===
Captured URI variables can be accessed with `@PathVariable`, as the following example shows:
Captured URI variables can be accessed with `@PathVariable`. For example:
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
@ -1646,32 +1645,29 @@ by using `PropertyPlaceHolderConfigurer` against local, system, environment, and
sources. You can use this, for example, to parameterize a base URL based on some external
configuration.
NOTE: Spring MVC uses the `PathMatcher` contract and the `AntPathMatcher` implementation from
`spring-core` for URI path matching.
[[mvc-ann-requestmapping-pattern-comparison]]
==== Pattern Comparison
[.small]#<<web-reactive.adoc#webflux-ann-requestmapping-pattern-comparison, WebFlux>>#
When multiple patterns match a URL, they must be compared to find the best match. This is done
by using `AntPathMatcher.getPatternComparator(String path)`, which looks for patterns that are more
specific.
When multiple patterns match a URL, the best match must be selected. This is done with
one of the following depending on whether parsed `PathPattern`'s are enabled for use or not:
A pattern is less specific if it has a lower count of URI variables (counted as 1), single
wildcards (counted as 1), and double wildcards (counted as 2). Given an equal score, the
longer pattern is chosen. Given the same score and length, the pattern with more URI variables
than wildcards is chosen.
* {api-spring-framework}/web/util/pattern/PathPattern.html#SPECIFICITY_COMPARATOR[`PathPattern.SPECIFICITY_COMPARATOR`]
* {api-spring-framework}/util/AntPathMatcher.html#getPatternComparator-java.lang.String-[`AntPathMatcher.getPatternComparator(String path)`]
Both help to sorts patterns with more specific ones on top. A pattern is less specific if
it has a lower count of URI variables (counted as 1), single wildcards (counted as 1),
and double wildcards (counted as 2). Given an equal score, the longer pattern is chosen.
Given the same score and length, the pattern with more URI variables than wildcards is
chosen.
The default mapping pattern (`/{asterisk}{asterisk}`) is excluded from scoring and always
sorted last. Also, prefix patterns (such as `/public/{asterisk}{asterisk}`) are considered less
specific than other pattern that do not have double wildcards.
For the full details, see {api-spring-framework}/util/AntPathMatcher.AntPatternComparator.html[`AntPatternComparator`]
in {api-spring-framework}/util/AntPathMatcher.html[`AntPathMatcher`] and also keep in mind that
you can customize the {api-spring-framework}/util/PathMatcher.html[`PathMatcher`] implementation.
See <<mvc-config-path-matching>> in the configuration section.
For the full details, follow the above links to the pattern Comparators.
[[mvc-ann-requestmapping-suffix-pattern-match]]
@ -5832,20 +5828,12 @@ The following example shows how to customize path matching in Java configuration
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseTrailingSlashMatch(false)
.setPathMatcher(antPathMatcher())
.setUrlPathHelper(urlPathHelper())
.setPatternParser(new PathPatternParser())
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
}
@Bean
public UrlPathHelper urlPathHelper() {
//...
}
@Bean
public PathMatcher antPathMatcher() {
//...
private PathPatternParser patternParser() {
// ...
}
}
----
@ -5858,20 +5846,11 @@ The following example shows how to customize path matching in Java configuration
override fun configurePathMatch(configurer: PathMatchConfigurer) {
configurer
.setUseSuffixPatternMatch(true)
.setUseTrailingSlashMatch(false)
.setPathMatcher(antPathMatcher())
.setUrlPathHelper(urlPathHelper())
.setPatternParser(patternParser)
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
}
@Bean
fun urlPathHelper(): UrlPathHelper {
//...
}
@Bean
fun antPathMatcher(): PathMatcher {
fun patternParser(): PathPatternParser {
//...
}
}