我正在为我的应用编写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")
这是最佳做法/适当吗?它将如何知道调用哪种方法?
提前感谢您的任何澄清。
答案 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
的讨论