Question

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!

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top