JAX-RS 从傻逼到牛叉 4:路径优先级规则

笼子大了什么鸟都有。同样的道理,不论多么细心地设计 URI 结构,在系统复杂到一定程度后,仍然难以避免路径冲突。为此,JAX-RS 使用一些规则来定义路径匹配的优先级。

如果某个请求路径可以对上多个 URI 匹配模式,那么 JAX-RS 就把可能匹配上的 URI 模式先拼接完整,按照下列规则依次进行比较,直到找出最适合的匹配模式:

  1. 首先,字面字符数量更多的 URI 模式优先。“字面字符”就是写死的路径段,不包含路径分隔符 / 和模板参数。例如 /ms/rest/movie/{id : \\d+} 包含 11 个字面字符。
  2. 其次,模板参数个数最多的 URI 模式优先。例如 /ms/rest/movie/{id : \\d+} 带一个模板参数。
  3. 最后,含正则表达式的模板参数个数最多的 URI 模式优先。例如 /ms/rest/movie/{id : \\d+} 带一个含正则表达式的模板参数。

现在看一个例子。回顾一下,/ms/rest/movie/{id : \\d+} 已经用来根据 ID 获取电影信息。为了制造麻烦,现在引入 /ms/rest/movie/{title} 来根据电影标题获取电影信息。先请你猜一猜 /ms/rest/movie/300 代表啥?ID 为 300 的神秘电影,还是我们可爱的勇士?只能跟着规则一条一条地看:

  1. 首先,两个 URI 匹配模式的字面字符都是 11,下一步。
  2. 其次,两个 URI 匹配模式都带一个模板参数,下一步。
  3. 最后,只有 /ms/rest/movie/{id : \\d+} 带了一个含正则表达式的模板参数,胜利!所以返回 ID 为 300 的片片。

传说这三条规则能够覆盖 90% 以上的情景。不过我们马上就能造出一个打破规则的东西:/ms/rest/movie/{title : [ \\w]+}。经过测试,/ms/rest/movie/300 会匹配上 /ms/rest/movie/{id : \\d+}。如何解释?JAX-RS 规范文档 3.7.2 定义了完整的匹配规则,对于这两个简单的 URI 匹配模式,似乎一直进行到底都无法比较出优先级。莫非有另外的潜规则?或者是 JAX-RS 的实现(参考实现为 Jersey)自行规定?但无论如何,搞出这种怪物本身就是一个设计错误,所以也不必去深究原因。

你可能感兴趣的:(JAX-RS 从傻逼到牛叉 4:路径优先级规则)