我无法到达正确的@Path
I cannot get to the correct @Path
使用 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(...)
?
TL;DR
删除 retrieveJob
方法中的 @Consumes(MediaType.APPLICATION_JSON)
。首先,它不接受 body,因此它不消耗任何东西。其次它与预期的行为冲突。
我已经用 Jersey 和 RESTeasy 进行了测试,这似乎在实现上有所不同。 Jersey 可以很好地处理您的代码,而 RESTeasy 总是会遇到 retrieveJob
方法,正如您遇到的那样。
这是我的看法。如果你看一下 JAX-RS spec; 3.7.2 Request Matching,有一个 semi-cryptic 匹配资源的算法,它是这样的。
- 获取所有匹配的资源class(按路径),将它们放入集合中。
- 获取所有匹配的资源方法(按路径),将它们放入集合中。
- 按最佳匹配路径对方法进行排序(大多数文字字符排在最前面)。
- 按媒体类型排序(使用消费和生产)。
从我的角度来看,在这种特殊情况下,在第 3 步之后,retrieveLastJob
应该会自动获胜,因为它具有最多的文字字符。生产媒体类型是相同的,消费媒体类型应该无关紧要,因为它是一个没有 Content-Type 进行任何匹配的 GET 请求。
我猜 RESTeasy 仍然使用注释来排序,即使在这种情况下甚至不应该考虑它。因此,带有注释的方法似乎具有更高的优先级,因为它 看起来 更具体,仅具有注释,而另一个则没有。但是在这种情况下(第 4 步)的特异性水平真的不重要。
我不知道这是否是违反规范的错误。目前还不太清楚应该如何处理,但我个人认为泽西岛的行为是正确的行为,因为在这种特殊情况下,这种特异性水平应该无关紧要。在任何情况下,对于没有 body.
的 GET 请求,无论如何使用 @Consumes
注释都是不正确的
使用 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(...)
?
TL;DR
删除 retrieveJob
方法中的 @Consumes(MediaType.APPLICATION_JSON)
。首先,它不接受 body,因此它不消耗任何东西。其次它与预期的行为冲突。
我已经用 Jersey 和 RESTeasy 进行了测试,这似乎在实现上有所不同。 Jersey 可以很好地处理您的代码,而 RESTeasy 总是会遇到 retrieveJob
方法,正如您遇到的那样。
这是我的看法。如果你看一下 JAX-RS spec; 3.7.2 Request Matching,有一个 semi-cryptic 匹配资源的算法,它是这样的。
- 获取所有匹配的资源class(按路径),将它们放入集合中。
- 获取所有匹配的资源方法(按路径),将它们放入集合中。
- 按最佳匹配路径对方法进行排序(大多数文字字符排在最前面)。
- 按媒体类型排序(使用消费和生产)。
从我的角度来看,在这种特殊情况下,在第 3 步之后,retrieveLastJob
应该会自动获胜,因为它具有最多的文字字符。生产媒体类型是相同的,消费媒体类型应该无关紧要,因为它是一个没有 Content-Type 进行任何匹配的 GET 请求。
我猜 RESTeasy 仍然使用注释来排序,即使在这种情况下甚至不应该考虑它。因此,带有注释的方法似乎具有更高的优先级,因为它 看起来 更具体,仅具有注释,而另一个则没有。但是在这种情况下(第 4 步)的特异性水平真的不重要。
我不知道这是否是违反规范的错误。目前还不太清楚应该如何处理,但我个人认为泽西岛的行为是正确的行为,因为在这种特殊情况下,这种特异性水平应该无关紧要。在任何情况下,对于没有 body.
的 GET 请求,无论如何使用@Consumes
注释都是不正确的