我正在使用Dropwizard,它在内部使用Jersey。 我在控制器上有两种方法:
PUT /garbage/[id1,id2,...idN]
旨在采用一个 path 参数,该参数是表示要更新的资源的数字 ID 列表。 我在这里使用基于正则表达式的PathParam
。 我在这个例子中捏造了正则表达式,因为我认为这并不重要,但关键是单个数字 ID 应该与正则表达式匹配。
GET /garbage/[id]
获取有关单个垃圾的数据。
泽西似乎感到困惑,尽管方法不同。 当我查询类似的东西时
curl localhost:8080/garbage/1
泽西岛给了我一个 405 错误。 如果我将 PUT 从图片中取出(例如,破坏路径参数正则表达式,或完全删除它(,GET 端点工作正常。
我假设 JAX-RS 3.7.2 中缺少一些细节来解释为什么会这样,但我无法弄清楚它是什么。
代码如下:
@Path("/garbage")
@Produces(MediaType.APPLICATION_JSON)
public class GarbageController {
private static final Logger LOG = LoggerFactory.getLogger(GarbageController.class);
@PUT
@Path("/{params: [\d,]+}")
@Consumes(MediaType.APPLICATION_JSON)
@Timed
public Response updateGarbage(@PathParam("params") List<PathSegment> params) {
LOG.warn("updateGarbage");
return Response.status(Response.Status.OK).build();
}
@GET
@Path("/{garbageId}")
public Response getGarbageById(@PathParam("garbageId") long garbageId) {
LOG.warn("getGarbage");
return Response.status(Response.Status.OK).build();
}
}
目的是处理 URI 的片段,这对于检索矩阵参数很有用。例如下面的方法:
@GET
@Path("/book/{id}")
public String getBook(@PathParam("id") PathSegment id) {...}
应该能够处理此请求:
GET /book;name=EJB 3.0;author=Bill Burke
由于@PathSegment截获整个 URL 片段,因此 GET 方法似乎被忽略了。您可以使用简单的字符串拆分来处理 PUT 请求上的逗号分隔 ID:
@PUT
@Path("/{params}")
@Consumes(MediaType.APPLICATION_JSON)
@Timed
public Response updateGarbage(@PathParam("params") String params) {
LOG.warn("updateGarbage ", params.split(","));
return Response.status(Response.Status.OK).build();
}
您还可以更改请求格式以查询参数或实现转换器/提供程序来处理自定义对象。所有这些都应该解决GET未实现的问题。
我相信这不是 GET 和 PUT 之间的路由优先级的情况,而是与不能在 GET 请求上使用的@Consumes注释有关。DW 忽略此终结点或将其转换为默认的 POST 方法,这将解释 GET 请求的 405 响应。
通了这一点,尽管我对泽西岛的了解还不够深,不知道它为什么有效。 解决方案是重写 @GET
方法以使用与@PUT
相同的正则表达式语法。 Jersey 将处理方法签名中的类型转换,请注意,如果类型转换失败(即 GET /garbage/xyz
(,它将返回 404
@PUT
@Path("/{params: .+}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateGarbage(@PathParam("params") List<PathSegment> params) {
LOG.warn("updateGarbage");
return Response.status(Response.Status.OK).build();
}
@GET
@Path("/{params: .+}")
public Response getGarbageById(@PathParam("params") long garbageId) {
LOG.warn("getGarbage {}", garbageId);
return Response.status(Response.Status.OK).build();
}