Jax-RS重载方法/路径执行顺序

时间:2015-06-07 06:57:50

标签: regex api rest jax-rs

我正在为我的应用编写API,我对Jax-RS如何处理某些情况感到困惑

例如,我定义了两条路径:

@Path("user/{name : [a-zA-Z]+}")

@Path("user/me")

我指定的第一条路径明确包含第二条路径,因为正则表达式包含所有字母a-z。但是,该程序似乎没有问题。是因为它默认为最具体的路径(即/ me然后查找正则表达式)?

此外,如果我将两个正则表达式定义为具有一些重叠的路径会发生什么。是否有一个默认方法将被调用?

假设我想为三种不同的方法创建三个路径:

@Path{"user/{name : [a-zA-Z]+}")
@Path("user/{id : \\d+}")
@Path("user/me")

这是最佳做法/适当吗?它将如何知道调用哪种方法?

提前感谢您的任何澄清。

1 个答案:

答案 0 :(得分:8)

这是在“匹配资源方法请求”中的the spec

  

使用(1)对每个成员中的文字字符数作为主键(降序)排序E(2)捕获组作为辅助键(降序),(3)具有非默认正则表达式的捕获组数(即不是'([^ /] +?)')作为三级密钥(降序),......

候选方法按指定的有序“密钥”排序。我用粗体突出显示它们。

第一个排序键是文字字符数。所以对于这三个

@Path{"user/{name : [a-zA-Z]+}")
@Path("user/{id : \\d+}")
@Path("user/me") 

如果请求的URI为../user/me,则始终会选择最后一个URI,因为它具有最多的文字字符(7,/计数)。其他人只有5人。

../users/me之外,其他任何内容../users/..都取决于正则表达式。在您的情况下,一个只匹配数字,一个只匹配字母。这两个正则表达式无法重叠。所以它会相应匹配。

现在只是为了好玩,让我们说我们有

@Path{"user/{name : .*}")
@Path("user/{id : \\d+}")
@Path("user/me")

如果你看一下前两个,我们现在有重叠的正则表达式。第一个匹配所有数字,第二个匹配。那么将使用哪一个?我们不能做任何假设。这是一个未指定的歧义程度,我看到了不同实现的不同行为。 AFAIK,没有“最佳匹配”正则表达式的概念。无论是匹配还是不匹配。

但是,如果我们希望始终首先检查{id : \\d+}该怎么办?如果它匹配数字,则应选择该数字。我们可以根据规范进行破解。规范谈到“捕获群体”,基本上是{..}。第二个排序键是捕获组的数量。我们破解它的方式是添加另一个“可选”组

@Path{"user/{name : .*}")
@Path("user/{id : \\d+}{dummy: (/)?}")

现在后者有更多的捕获组,所以它总是在排序中领先。它所做的只是允许一个可选的/,它不会真正影响API,但确保如果请求URI是所有数字,则始终会选择此路径。

您可以看到与某些测试用例in this answer

的讨论