两个Spring控制器匹配同一个URL导致错误的控制器调用。

3
我们有两个Spring控制器存在干扰的问题。其中一个控制器通过通配符前缀匹配URL后缀,另一个控制器则通过URL前缀匹配。我期望URL从左到右被读取,但事实似乎并非如此。
请考虑以下代码(已编辑):
    @RequestMapping(value = "/**/abcdefg")
    public class Controller1 {...}

    @RequestMapping(value = "/**/xyz")
    public class Controller2 {...}

    @RequestMapping(value = "/some/{path}")
    public class Controller3 
    {
        @RequestMapping(value = "/{page}", method = RequestMethod.GET)
        public String page(@PathVariable("page") final String page, final Model model)
        { //do sth }
    }

问题在于,如果调用URL“/some/path/abcdefg”,则控制器1会启动。但我想要的是控制器3。
不幸的是,其他控制器的行为与此不同!
如果调用URL“/some/path/xyz”,则控制器3会启动。这种行为对于控制器是可重现的。它总是表现相同,并且控制器不会随机选择。
Spring文档以及其他用户的问题都指向了这样一个想法,即采取与给定模式匹配的“第一个”控制器。然而,这对我来说并不太合理,因为控制器1和2具有非常相似的请求映射,但控制器的匹配却不同!
所有内容都由调度程序servlet处理。
是否有人能提示可能发生了什么?

2
映射到 /some/path 的控制器将无法处理 /some/path/xyz。请向我们展示您真正的映射。 - Sotirios Delimanolis
2
“/some/path”如何与“/some/path/abcd”匹配?它们显然不相等。真正的路径是什么? - JB Nizet
感谢你的快速评论!我已经编辑了代码。确实有一个带有请求映射的控制器方法,有时会接收调用,有时则不会。 - Felix
1个回答

7

我希望URL从左到右读取,但实际情况并非如此。你是对的,这不是这种情况。映射是通过特定性来解决的,相关文档部分可以在这里找到。

具有较少URI变量和通配符数量的模式被认为更加具体化。例如,/hotels/{hotel}/* 具有1个URI变量和1个通配符,比 /hotels/{hotel}/** 更加具体化,后者有1个URI变量和2个通配符。

如果两个模式具有相同数量,则较长的模式被视为更具体。例如,/foo/bar*/foo/* 更长且更具体。

当两个模式具有相同的计数和长度时,具有更少通配符的模式被视为更具体。例如,/hotels/{hotel}/hotels/* 更具体。

如果两个映射与请求匹配,则将应用更具体的映射。根据您的要求制定映射以遵循特定性规则。


非常感谢您!您刚刚救了我的一天。我刚刚编辑了我的问题,指出您是正确的。 "//abcdefg","//xyz"和"/some/{path}/{page}"具有相同数量的uri-vars /通配符。 无论如何,“abcdefg”的字符比“some”多,“xyz”的字符比“some”少。 这意味着,Spring将“abcdefg”处理为最具体的匹配项,然后是“some”,然后是“xyz” 万岁。这应该以大写字母打印在Spring启动页面上。 - Felix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接