如何设置Spring MVC映射的优先级?

时间:2013-01-21 14:41:48

标签: java spring spring-mvc

我有2个弹簧控制器映射:

@Controller
public class ContentController {

    @RequestMapping(value = "**/{content}.html")
    public String content(@PathVariable String content, Model model, HttpServletRequest request) {
    }
}

@Controller
public class HomeController {

    @RequestMapping(value = "**/home")
    public String home(HttpServletRequest request, Model model) {
    }
}

以下网址匹配两个映射: /home.html

但是,我想确保'内容'映射始终优先于'home'映射。有没有办法可以指明?

4 个答案:

答案 0 :(得分:4)

最近我遇到了类似的问题:我有两种不明确的网址:

  • 一个人接受了一年,比如/2012/2013等。我使用正则表达式创建了这样的表格:@RequestMapping("/{year:(?:19|20)\\d{2}}")
  • 另一个是接受内容标识符(aka slug)。我使用@RequestMapping("/{slug}")
  • 等映射创建了它

重要的是"年"控制器方法优先于" slug"一。不幸的是(对我而言)Spring总是使用" slug"控制器方法。

由于Spring MVC更喜欢更具体的映射,我不得不制作我的" slug"模式不太具体。根据{{​​3}}文档,我在slug映射中添加了通配符:@RequestMapping("/{slug}**")

我的控制器看起来像这样,现在listByYear在一年(/2012/1998等)在网址中时被调用。

@Controller
public class ContentController
{
    @RequestMapping(value = "/{slug}**")
    public String content(@PathVariable("slug") final String slug)
    {
        return "content";
    }
}

@Controller
public class IndexController
{
    @RequestMapping("/{year:(?:19|20)\\d{2}}")
    public String listByYear()
    {
        return "list";
    }
}

这并不是如何设置优先级(在我看来这将是一个惊人的功能),但提供某种"很好的"解决方法,将来可能会派上用场。

答案 1 :(得分:0)

URL映射由发现映射的顺序决定。

因此,您可以强制在另一个控制器之后的spring上下文中创建一个控制器。

可以使用bean定义中的depends-on =“”属性(在xml中)来完成。

我不确定它是使用它找到的第一个映射还是最后一个映射。

另外,这只是理论,我实际上没有尝试过这个。

我看到这样的日志消息:

17:29:01.618 [main] INF S o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/resources/**] onto handler    'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0'
17:29:01.625 [main] INF S o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'

非常值得在SimpleUrlHandlerMapping上看看它是如何工作的。

答案 2 :(得分:0)

对特定的的自动排序现在可以正常工作了。 (使用Spring 5.0.10)

AntPatternComparator

        /**
         * Compare two patterns to determine which should match first, i.e. which
         * is the most specific regarding the current path.
         * @return a negative integer, zero, or a positive integer as pattern1 is
         * more specific, equally specific, or less specific than pattern2.
         */
        @Override
        public int compare(String pattern1, String pattern2)

AbstractUrlHandlerMapping::lookupHandler(String urlPath, HttpServletRequest request)中使用了哪个

        Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
        if (!matchingPatterns.isEmpty()) {
            matchingPatterns.sort(patternComparator);
            if (logger.isDebugEnabled()) {
                logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
            }
            bestMatch = matchingPatterns.get(0);
        }

答案 3 :(得分:-3)

此网址(/home.html)与两个映射都不匹配:

    @RequestMapping(value = "**/{content}.html")
    ...
    @RequestMapping(value = "**/home")
    …

它只匹配第一个,因为它有一个后缀“ .html ”!