Jersey 2.6子资源无常量路径时可选路径参数异常原因咨询
这问题挺有意思的,我来帮你拆解背后的原因,顺便给你靠谱的解决办法。
核心问题:路径参数的贪婪匹配
你最初写的路径表达式/{device}/{property}{p:/?}{field:([a-zA-Z][a-zA-Z0-9_]*)?}里,{property}没有指定正则限制,Jersey默认的路径参数匹配是贪婪模式——它会尽可能匹配更多内容,甚至包括/字符。
当你请求/device001/property001/field001时,Jersey会把property001/field001整个当成{property}的取值,{p}和{field}都为空。这时候这个请求根本没匹配到你写的合并方法,反而可能匹配到了其他资源(比如某个定义了@Path("/{device}/{property}")的资源类,但这个类没有实现GET方法),所以返回了405 Method Not Allowed。
而当你加上just2C/前缀后,路径变成/just2C/{device}/{property}{p:/?}{field:...?},Jersey的匹配器会因为固定前缀的存在,更清晰地识别路径层级,不会让{property}跨/匹配,而是把property001分配给{property},/分配给{p},field001分配给{field},自然就能正确匹配到你的方法了。
额外因素:Jersey 2.6的版本特性
Jersey 2.6属于比较早期的2.x版本,它的路径匹配器在处理根路径下的可选路径片段时,确实存在一些不够完善的地方。固定前缀的加入相当于给匹配器一个明确的“锚点”,避免了它在根路径下的模糊匹配逻辑。
解决方案:给property参数加正则限制
不用依赖额外前缀,只要给{property}加上正则,限制它只能匹配单个路径段(不能包含/),就能彻底解决问题:
@GET @Path("/{device}/{property:[^/]+}{p:/?}{field:([a-zA-Z][a-zA-Z0-9_]*)?}") @Produces(MediaType.APPLICATION_JSON) public Response getParameterOrFieldValue( @PathParam("device") final String device, @PathParam("property") final String property, @PathParam("field") final String field ) { // 你的业务逻辑:如果field为空,执行原getParameterValue逻辑;否则执行getFieldValue逻辑 }
这里的[^/]+表示匹配任意非/的字符,确保{property}只会匹配到下一个/之前的内容,不会跨段匹配。
这样修改后,不管是带field还是不带field的请求,都能正确匹配到这个方法。
内容的提问来源于stack exchange,提问作者Meziane

