diff --git a/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java b/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java
index 84b409b168f..0b69eed122e 100644
--- a/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java
+++ b/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java
@@ -47,9 +47,12 @@ import org.springframework.util.StringUtils;
* and captures it as a variable named "spring"
*
*
- * Notable behavior difference with {@code AntPathMatcher}:
- * {@code **} and its capturing variant {*spring} cannot be used in the middle of a pattern
- * string, only at the end: {@code /pages/{**}} is valid, but {@code /pages/{**}/details} is not.
+ *
Note: 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 {*spring}. The aim is to eliminate ambiguity when
+ * comparing patterns for specificity.
*
*
Examples
*
diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc
index 747b9eb0483..739d769092d 100644
--- a/src/docs/asciidoc/web/webmvc.adoc
+++ b/src/docs/asciidoc/web/webmvc.adoc
@@ -1529,40 +1529,39 @@ The following example has type and method level mappings:
==== URI patterns
[.small]#<>#
-You can map requests by using glob patterns and wildcards:
-
-[cols="2,3,5"]
-|===
-|Pattern |Description |Example
-
-| `+?+`
-| Matches one character
-| `+"/pages/t?st.html"+`
-
-matches `+"/pages/test.html"+`
-and `+"/pages/t3st.html"+`
-
-| `+*+`
-| Matches zero or more characters within a path segment
-| `+"/resources/*.png"+` matches `+"/resources/file.png"+`
-
-`+"/projects/*/versions"+` matches `+"/projects/spring/versions"+` but does not match `+"/projects/spring/boot/versions"+`
-
-| `+**+`
-| 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:
+`@RequestMapping` methods can be mapped using URL patterns. There are two alternatives:
+
+* `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.
+
+`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
+<>.
+
+`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].
+
+Some example patterns:
+
+* `+"/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
+
+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]#<>#
-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 <> 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 {
//...
}
}