泽西岛 2.x - PUT和GET的路由优先级冲突



我正在使用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();
    }
}
@PathSegment的主要

目的是处理 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();
}

最新更新