【问题标题】:Jersey 2.x - Conflicting route priority of PUT and GETJersey 2.x - PUT 和 GET 的路由优先级冲突
【发布时间】:2017-06-15 06:12:18
【问题描述】:

我正在与 Dropwizard 合作,它在内部使用 Jersey。我在控制器上有两种方法:

PUT /garbage/[id1,id2,...idN] 旨在采用路径参数,该参数是表示要更新的资源的数字 ID 列表。我在这里使用基于正则表达式的PathParam。我在这个例子中捏造了正则表达式,因为我认为这并不重要,但关键是单个数字 ID 应该与正则表达式匹配。

GET /garbage/[id] 获取有关单个垃圾的数据。

Jersey 似乎有些困惑,尽管方法不同。当我用类似的东西查询时

curl localhost:8080/garbage/1

Jersey 给我一个 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();
    }
}

【问题讨论】:

    标签: java rest jersey dropwizard


    【解决方案1】:

    @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();
    }
    

    您还可以将请求格式更改为query parameters 或实现Converter/Provider 来处理自定义对象。他们都应该解决 GET 未实现的问题。

    我相信这不是 GET 和 PUT 之间路由优先级的情况,而是这与不能用于 GET 请求的 @Consumes 注释有关。 DW 要么忽略此端点,要么将其转换为默认的 POST 方法,这将解释 GET 请求的 405 响应。

    【讨论】:

    • 感谢您的回答!不幸的是,\@Consumes 不是问题。我在有和没有 \@Consumes 的情况下都试过了,它对行为没有影响。 (我最初写这段代码时没有\@Consumes,然后作为随机实验添加,然后忘记删除它。我将返回并从示例代码中删除\@Consumes 以明确这一点。)
    【解决方案2】:

    我发现了这一点,尽管我对泽西岛的追踪还不够远,无法知道它为什么起作用。解决方案是重写@GET 方法以使用与@PUT 相同的正则表达式语法。 Jersey 将在方法签名中处理类型转换,注意如果类型转换失败,它将返回 404(即GET /garbage/xyz)。

    @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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 2014-07-23
      • 1970-01-01
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 2017-09-19
      相关资源
      最近更新 更多