I have the following mappping:
<bean id="controllerMappingProperties" class="java.util.Properties">
<constructor-arg>
<props>
<prop key="/service/q-*-fltr-brand-_-*-find-html.html">redirectController</prop>
<prop key="/service/q">queryController</prop>
<prop key="/service/q-*.html">queryController</prop>
</props>
</constructor-arg>
</bean>
So the URL
http://localhost:8080/service/q-foo-fltr-brand-_-bar-find-html.html
should map to the redirectController but it maps to queryController.
If I change the first mapping to
<prop key="/service/q-*-fltr-brand-_-bar-find-html.html">redirectController</prop>`
or
<prop key="/service/q-foo-fltr-brand-_-*-find-html.html">redirectController</prop>
the mapping works correctly.
Using two single stars in the pattern works with other mappings, so that can't be the problem. What am I doing wrong?
Thanks for help!
I came across a similar question a few days ago. The problem lies in the AntPatternComparator
which is used to sort the collection of matches paths.
In your case change your path from /service/q-*.html
to /service/q-**.html
. It does not make the most sense but it should work.
If you look at RequestMappingInfo.getMatchingCondition
, the method for getting the matching conditions for the current request, you'll see the following comment which states that the best matching pattern will be first in the list.
Spring 4 source
/**
* Checks if all conditions in this request mapping info match the provided request and returns
* a potentially new request mapping info with conditions tailored to the current request.
* <p>For example the returned instance may contain the subset of URL patterns that match to
* the current request, sorted with best matching patterns on top.
* @return a new instance in case all conditions match; or {@code null} otherwise
*/
@Override
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
// ...
}
The AntPatternComparator
will basically rely on the amount of *
and {
present in the pattern. If their numbers are the same the pattern lengths will be compared. When sorting the collection of patterns with a AntPatternComparator
your /service/q-foo-fltr-brand-_-*-find-html.html
path will be greater then /service/q-*.html
based on length. So /service/q-*.html
will end on top.
Adding the extra wildcard makes /service/q-**.html
the greatest since it's wildcard count is higher.