如何在Jersey客户端的DELETE请求中发送封装数据?

时间:2014-08-10 15:04:16

标签: java rest jersey jax-rs

我在Jersey 2.x中有以下服务器端代码:

@Path("/store/remove/from/group")
@DELETE
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
public Response removeStoresFromGroup(@FormParam("storeName") List<String> storeNames, @FormParam("groupName") String groupName) {
    //......
}

在客户端,我想使用Jersey 2.x客户端向上述Web服务发送删除请求。但是,从Jersey client API的文档中,我没有找到如何在DELETE请求中包含以下数据:

WebTarget webTarget = client.target("/store/remove/from/group");
MultivaluedMap<String, String> formData = new MultivaluedHashMap<String, String>();
List<String> storeName = new ArrayList<String>();
storeName.add("Store1");
storeName.add("Store2");
storeName.add("Store3");

formData.addAll("storeName", storeName);
formData.add("groupName", "Group A");

Response response = webTarget.request().accept(MediaType.TEXT_PLAIN).delete();   //The delete() method doesn't take any entity body in the request.

在Jersey客户端API中,SyncInvoker类不支持以实体主体为参数的delete方法。所以我只能使用POST或PUT将数据发送到服务器,如下所示(但不是DELETE):

Response response = webTarget.request().accept(MediaType.TEXT_PLAIN).post(Entity.form(formData)); 

但我想使用DELETE请求,因为请求正在删除一些资源。如何通过Jersey客户端发送带有一些实体数据的DELETE请求?

5 个答案:

答案 0 :(得分:21)

根据Jersey 2.18版本中的代码,类JerseyInvocation使用预定义的HashMap来验证HTTP方法及其实体,如下所示:

map.put("DELETE", EntityPresence.MUST_BE_NULL);
map.put("GET", EntityPresence.MUST_BE_NULL);
...

这就是我们收到此错误的原因“对于http方法DELETE,实体必须为null”。

虽然请注意,它还提供了一个Jersey客户端配置属性ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION来确定是否停止其余的执行,所以我们可以使用此属性来禁止验证以继续发送{ {1}}请求实体。例如

DELETE

答案 1 :(得分:6)

请注意:如果您使用resteasy JAX RS Client API的实施,则可以使用build().invoke()

client.target("$baseUrl$restEndPoint/$entityId")
                .request("application/json")
                .build("DELETE", Entity.entity(entity, MediaType.APPLICATION_JSON))
                .invoke()

但它不适用于jersey

答案 2 :(得分:4)

具有实体正文is not strictly forbiddenDELETE,但它非常罕见并被某些框架/服务器忽略。实体主体的需要可能表明未按预期使用DELETE

例如:如果GET /customers/4711返回一位客户而您发送DELETE /customers/4711,则此资源上的下一个GET应返回404。您删除了由网址标识的资源,如defined in the spec

您的网址/store/remove/from/group似乎无法识别资源。使用/store/4711/groups/4711等标识符并在其上发送DELETE将无法满足您的需求,因为您希望&#34;从群组中删除商店&#34;不要删除商店或组。

假设您有一个组资源

{
  "id" : 4711,
  "stores" : [123, 456, 789]
}

你想要一个像

这样的结果
{
  "id" : 4711,
  "stores" : [123, 789]
}

你没有删除任何东西。您正在修改资源,因此PUTPOSTPATCH是合适的方法。 JSON-Patch是描述此类更改的良好格式。请求看起来像这样:

PATCH /groups/4711 HTTP/1.1
Content-Type: application/json-patch

[
  {
    "op" : "remove"
    "path" : "stores/1"
  }
]

答案 3 :(得分:2)

您可以使用webTarget.request().accept(MediaType.TEXT_PLAIN).method("DELETE",yourEntity)来调用其中包含实体的DELETE

答案 4 :(得分:0)

我还使用了 RESTeasy Jersey 客户端并为我工作:

响应 response = client.target(yourUrlToCall).request(MediaType.APPLICATION_JSON) .build("DELETE", Entity.entity(yourJsonDTO, MediaType.APPLICATION_JSON)).invoke();

对于解决一些正常使用get()、delete()等“不允许”的复杂场景非常有用