Java 如何在 Jersey 客户端的 DELETE 请求中发送包含数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25229880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:56:03  来源:igfitidea点击:

How to send enclose data in DELETE request in Jersey client?

javarestjerseyjax-rs

提问by tonga

I have the following server-side code in Jersey 2.x:

我在 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) {
    //......
}

On client side, I want to use Jersey 2.x client to send a delete request to the above web service. However, from the documentation of Jersey client API, I didn't find how to enclose the following data in DELETE request:

在客户端,我想使用 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.

From the Jersey client API, the SyncInvokerclass doesn't support a deletemethod with entity body as its argument. So I can only use either POST or PUT to send the data to the server like the following (but not for DELETE):

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

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

But I want to use DELETE request since the request is deleting some resources. How to send DELETE request with some entity data via Jersey client?

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

采纳答案by lefloh

A DELETEwith an entity body is not strictly forbiddenbut it's very uncommon and ignored by some frameworks/servers. The need of an entity body may indicate that a DELETEis not used as it is intended.

DELETE带有实体主体的A不是严格禁止的,但它非常不常见并且被某些框架/服务器忽略。实体主体的需要可能表明 aDELETE未按预期使用。

For instance: If a GET /customers/4711returns one customer and you send a DELETE /customers/4711the next GETon this resource should return a 404. You deleted a resource identified by a URLlike defined in the spec.

例如:如果 aGET /customers/4711返回一个客户并且您在此资源上发送DELETE /customers/4711下一个客户GET应该返回一个404. 您删除了由 URL 标识的资源规范中定义的那样

Your URL /store/remove/from/groupdoes not seem to identify a resource. Using identifiers like /store/4711or /groups/4711and sending a DELETEon them would not fit your needs because you want to "remove a store from a group" not delete a store or a group.

您的 URL/store/remove/from/group似乎没有标识资源。使用像/store/4711或这样的标识符/groups/4711DELETE在它们上发送 a不符合您的需求,因为您想“从组中删除商店”而不是删除商店或组。

Assuming you have a group resource

假设你有一个组资源

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

and you want a result like

你想要这样的结果

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

you are not deleting anything. You are modifying a resource so PUT, POSTor PATCHare appropiate methods. JSON-Patchis a good format for describing such changes. A request would look like this:

你没有删除任何东西。您正在修改资源PUTPOST或者PATCH是适当的方法。JSON-Patch是描述此类更改的好格式。请求将如下所示:

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

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

回答by John Ament

You can use webTarget.request().accept(MediaType.TEXT_PLAIN).method("DELETE",yourEntity)to invoke a DELETEwith an entity in it.

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

回答by CarlJi

Based on the code in Jersey 2.18 version, The class JerseyInvocationuse a predefined HashMap to validate HTTP method and its Entity as below:

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

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

That's why we got this error "Entity must be null for http method DELETE".

这就是为什么我们收到此错误“http 方法 DELETE 的实体必须为空”的原因。

While, please note that it also provide a Jersey client configuration property ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATIONto determine whether to stop the rest execution or not, so here we can use this property to suppress validation in order to continue to send a DELETErequest with Entity. e.g.

同时,请注意,它也提供了一个 Jersey 客户端配置属性ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION来决定是否停止其余的执行,所以这里我们可以使用这个属性来抑制验证,以便继续向DELETEEntity发送请求。例如

    ClientConfig config = new ClientConfig();
    config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
    Client client = ClientBuilder.newClient(config);
    ...

回答by Alexandr

Just to note: if you use resteasyimplementation of JAX RS Client API, you may use build().invoke():

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

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

But it does not work with jersey

但它不适用于 jersey