这是在“将请求与资源方法匹配”中的the spec
对E进行排序,使用(1)每个成员中文字字符的数量作为主键(降序),(2)捕获组的数量作为辅助键(降序),(3) 使用非默认正则表达式(即不是 '([^ /]+?)')作为第三键的捕获组的数量(降序顺序),...
会发生的是候选方法按指定的有序“键”排序。我用粗体突出显示它们。
第一个排序键是文字字符的数量。所以对于这三个
@Path{"user/{name : [a-zA-Z]+}")
@Path("user/{id : \\d+}")
@Path("user/me")
如果请求的 URI 是 ../user/me,将始终选择最后一个,因为它具有最多的文字字符(7 个,/ 计数)。其他的只有 5 个。
除了../users/me 之外的任何其他../users/.. 都将取决于正则表达式。在您的情况下,一个只匹配数字,一个只匹配字母。这两个正则表达式无法重叠。所以它会相应地匹配。
现在只是为了好玩,假设我们有
@Path{"user/{name : .*}")
@Path("user/{id : \\d+}")
@Path("user/me")
如果您查看前两个,我们现在有重叠的正则表达式。第一个将匹配所有数字,第二个也将匹配。那么将使用哪一个呢?我们无法做出任何假设。这是一个未指定的歧义级别,我已经看到来自不同实现的不同行为。 AFAIK,没有“最佳匹配”正则表达式的概念。要么匹配,要么不匹配。
但是,如果我们希望始终首先检查 {id : \\d+} 怎么办。如果它与数字匹配,那么应该选择它。我们可以根据规范破解它。该规范谈到了基本上是{..}s 的“捕获组”。第二个排序键是捕获组的数量。我们可以破解它的方法是添加另一个“可选”组
@Path{"user/{name : .*}")
@Path("user/{id : \\d+}{dummy: (/)?}")
现在后者有更多的捕获组,所以它总是在排序中领先。它所做的只是允许一个可选的/,这并不真正影响API,但确保如果请求URI 是全数字,则始终选择此路径。
你可以看到一些测试用例的讨论in this answer