问题描述
使用JAX-RS,我有以下3个@Path
s。
@Path(JobRest.PATH)
@Api(value = JobRest.PATH, description = "REST APIs for Jobs")
public interface JobRest {
public static final String PATH = "/job";
@GET
@Path("/last")
@Produces(MediaType.APPLICATION_JSON)
public Job retrieveLastJob(...);
@GET
@Path("/{jobId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Job retrieveJob(...., @PathParam("jobId") String jobId, );
@GET
@Produces(MediaType.APPLICATION_JSON)
public JobList retrieveAllJobs(....);
}
-
/job
正确调用retrieveAllJobs()
-
/job/1236
正确调用retrieveJob(..., "1236", ...)
。
我期望/job/last
会调用retrieveLastJob(...)
,因为它匹配,但它调用retrieveJob(..., "last", ...)
。
如何更改符号,以便/job/last
将调用retrieveLastJob(...)
?
1楼
TL; DR
删除retrieveJob
方法上的@Consumes(MediaType.APPLICATION_JSON)
。
首先,它不接受身体,所以它不消耗任何东西。
其次,它与预期的行为相冲突。
我已经使用Jersey和RESTeasy进行了测试,这似乎与实施有所不同。
Jersey可以很好地处理您的代码,而RESTeasy总是会遇到您正在遇到的retrieveJob
方法。
这是我的看法。 如果你看看 ,有一个用于匹配资源的半隐秘算法,就像这样。
- 获取所有匹配的资源类(按路径),将它们放入集合中。
- 获取所有匹配的资源方法(按路径),将它们放入集合中。
- 通过最佳匹配路径对方法进行排序(大多数文字字符首先出现)。
- 按媒体类型排序(消费和生产)。
从我的角度来看,在这种特殊情况下,在步骤3之后, retrieveLastJob
应该自动获胜,因为它具有最多的文字字符。
生产媒体类型是相同的,并且消费媒体类型甚至不应该重要,因为它是没有Content-Type的GET请求以进行任何匹配。
我猜它RESTeasy仍然使用注释进行排序,即使在这种情况下甚至不应该考虑它。 因此,看起来带有注释的方法具有更多的优先级,因为它看起来更具体,仅通过注释,而另一方则没有。 但在这种情况下,那个(第4步)特异性水平确实无关紧要。
我不知道这是不是违反规范的错误。
关于如何处理它并不是很清楚,但我个人认为泽西岛行为是正确的行为,因为在这种特殊情况下这种特异性水平无关紧要。
在任何情况下,对于没有正文的GET请求,无论如何都要使用@Consumes
注释是不正确的。