10

我有 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) {
    }
}

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

但是,我想确保“内容”映射始终优先于“家庭”映射。有没有办法可以指定?

4

4 回答 4

7

我最近遇到了非常相似的问题,我不得不使用两种模棱两可的 URL:

  • 一个人接受了一年,比如说/2012/2013等等。我使用带有正则表达式的映射来创建它,如下所示:@RequestMapping("/{year:(?:19|20)\\d{2}}")
  • 另一个是接受内容标识符(又名 slug)。我使用映射创建它,如@RequestMapping("/{slug}").

重要的是“年”控制器方法优先于“蛞蝓”方法。不幸的是(对我来说)Spring 总是使用“slug”控制器方法。

由于 Spring MVC 更喜欢更具体的映射,我不得不让我的“slug”模式不那么具体。基于路径模式比较文档,我在 slug 映射中添加了通配符:@RequestMapping("/{slug}**")

我的控制器看起来像这样,现在在 URL 中有年份(等)时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";
    }
}

这不完全是如何设置优先级(在我看来这将是一个了不起的功能),但提供了某种“不错”的解决方法,并且将来可能会派上用场。

于 2015-01-11T07:45:58.283 回答
0

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

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

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

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

另外,这只是理论,我还没有真正尝试过。

我看到这样的日志消息:

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 看看它是如何工作的。

于 2013-01-21T16:54:43.313 回答
0

现在,根据具体情况自动排序确实可以正常工作。(使用弹簧 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);
        }
于 2019-05-10T13:50:57.860 回答
-3

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

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

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

于 2013-01-22T05:41:56.103 回答