Jersey 2.x - PUT和GET的冲突路由优先级

时间:2017-06-13 21:09:58

标签: java rest jersey dropwizard

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

class MatrixButton { private int column; private int row; private JButton button = new JButton(); private int value; public MatrixButton(int column, int row, int value) { this.column = column; this.row = row; setValue(value); } public void addActionListener(ActionListener listener) { button.addActionListener(listener); } public int getColumn() { return column; } public int getRow() { return row; } public JButton getButton() { return button; } public int getValue() { return value; } public final void setValue(int value) { this.value = value; button.setText("" + value); } } 旨在获取路径参数,该参数是表示要更新的资源的数字ID列表。我在这里使用基于正则表达式的PUT /garbage/[id1,id2,...idN]。我在这个例子中捏造了正则表达式,因为我认为这不重要,但重点是单个数字ID应该与正则表达式匹配。

PathParam获取有关单件垃圾的数据。

尽管方法不同,但泽西岛似乎感到困惑。当我用

之类的东西查询时
GET /garbage/[id]

泽西岛给我一个405错误。如果我从图片中取出PUT(例如,破坏路径param正则表达式,或者完全删除它),GET端点工作正常。

我假设JAX-RS 3.7.2中有一些细节我错过了解释为什么会这样,但我无法弄清楚它是什么。

以下是代码:

curl localhost:8080/garbage/1

2 个答案:

答案 0 :(得分:0)

@PathSegment的主要目的是处理URI的片段,这对于检索Matrix参数很有用。例如,以下方法:

@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之间的路由优先级的情况,而是与@Consumes注释有关,它不能用于GET请求。 DW正在忽略此端点或将其转换为默认的POST方法,这将解释GET请求的405响应。

答案 1 :(得分:0)

我想到了这一点,虽然我没有追溯到泽西岛,知道它为什么会起作用。解决方案是重写@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();
}