1

我刚刚开始使用Jersey为我的网站创建一个 RESTful API。与我自己在 Java 中对 RESTful 服务的支持相比,这是一个奇妙的变化。我似乎无法弄清楚的一件事是如何“伪造” DELETE 和 PUT 方法。

Jersey 支持注释 @PUT 和 @DELETE,但是许多负载平衡器不允许这些方法通过。过去,我依赖于在 POST 请求中定义自定义 HTTP 标头(例如 x-method-override: DELETE)和“隧道”的能力。

有没有人找到一种方法将使用 Jersey/JAX-RS 注释的方法绑定到自定义标头?或者,是否有更好的方法来解决缺乏对 PUT 和 DELETE 的支持?

4

2 回答 2

2

这就是我决定在我的 API 中处理这种情况的方式。它相对简单,不需要太多额外的编码。为了说明,考虑一个用于地址的 RESTful api:

@Path("/address")
public class AddressService {

    @GET
    @Produces("application/xml")
    public StreamingOutput findAll() { ... }

    @POST
    @Produces("application/xml")
    @Consumes("application/x-www-form-urlencoded")
    public StreamingOutput create(...) { ... }

    //
    // This is the alternative to a "PUT" method used to indicate an "Update"
    // action.  Notice that the @Path expects "/id/{id}" which allows 
    // us to bind to "POST" and not get confused with a "Create"
    // action (see create() above).
    //
    @POST
    @Produces("application/xml")
    @Consumes("application/x-www-form-urlencoded")
    @Path("/id/{id}")
    public StreamingOutput update(@PathParam("id") Long id, ...) { ... }

    //
    // This is the typical "GET" method with the addition of a check
    // for a custom header "x-method-override" which is designed to 
    // look for inbound requests that come in as a "GET" but are 
    // intended as "DELETE".  If the methodOverride is set to "DELETE"
    // then the *real* delete() method is called (See below)
    //
    @GET
    @Produces("application/xml")
    @Path("/id/{id}")
    public StreamingOutput retrieve(
      @PathParam("id") Long id, 
      @HeaderParam("x-method-override") String methodOverride)
    {
      if (methodOverride != null && methodOverride.equalsIgnoreCase("DELETE")) {
        this.delete(id);
      }

      ...
    }


    // 
    // This is the typical "DELETE" method.  The onlything special about it is that
    // it may get invoked by the @GET equivalent is the "x-method-override" header
    // is configured for "DELETE"
    //
    @DELETE
    @Produces("application/xml")
    @Path("/id/{id}")
    public StreamingOutput retrieve(@PathParam("id") Long id) { ... }

}

于 2009-09-28T03:21:33.367 回答
1

它不再是真正的 REST,但在类似的情况下,我们将 POST /collection/ 定义为插入(正常),将 POST /collection/{id} 定义为更新,将没有正文的 POST /collection/{id} 定义为删除。

于 2011-07-05T21:16:24.350 回答