Java 如何在Jersey客户端的删除请求中发送封闭数据?

Java 如何在Jersey客户端的删除请求中发送封闭数据?,java,rest,jersey,jax-rs,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

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

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

您可以使用
webTarget.request().accept(MediaType.TEXT\u PLAIN).method(“DELETE”,您的实体)
调用包含实体的
DELETE

a
DELETE
,但这是非常罕见的,被一些框架/服务器忽略。实体主体的需要可能表明
删除
未按预期使用

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

您的URL
/store/remove/from/group
似乎无法识别资源。使用诸如
/store/4711
/groups/4711
之类的标识符并在其上发送
DELETE
将不符合您的需要,因为您希望“从组中删除存储”,而不是删除存储或组

假设您有一个组资源

{
  "id" : 4711,
  "stores" : [123, 456, 789]
}
你想要的结果是

{
  "id" : 4711,
  "stores" : [123, 789]
}
您没有删除任何内容。您正在修改资源,因此
PUT
POST
PATCH
是合适的方法。是描述此类更改的良好格式。请求如下所示:

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

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

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

map.put("DELETE", EntityPresence.MUST_BE_NULL);
map.put("GET", EntityPresence.MUST_BE_NULL);
...
这就是为什么我们得到这个错误“http方法删除的实体必须为空”

同时,请注意,它还提供了一个Jersey客户端配置属性
ClientProperties。抑制\u HTTP\u COMPLIANCE\u VALIDATION
以确定是否停止rest执行,因此这里我们可以使用此属性抑制验证,以便继续发送实体的
DELETE
请求。e、 g

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

需要注意的是:如果使用
resteasy
实现
JAX-RS客户端API
,则可以使用
build().invoke()


但它不适用于
jersey

我还使用了RESTeasy jersey客户端,并为我的:

Response-Response=client.target(yourUrlToCall.request(MediaType.APPLICATION_JSON) .build(“DELETE”,Entity.Entity(yourjsondo,MediaType.APPLICATION_JSON)).invoke()


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

OT但通常不需要发送带有delete的实体“delete方法请求源服务器删除请求URI标识的资源”。您的方法引用听起来更像是更新引用然后删除资源。有时,如果我想删除某些满足某些条件的数据,我需要在删除请求的实体体中传入一些参数。当我使用此方法时,它会报告错误:“http方法删除的实体必须为null”。为什么?嗯,我真的没想到。如果您查看第9.6节中的[1],您会发现
DELETE
是基于URI的。但它并没有说它不能使用身体。。[1] :我不明白为什么删除请求不能包含文档中的实体体。但是javadoc()没有说它也不能使用DELETE作为方法名。谢谢你的建议。Jersey框架目前似乎不支持
PATCH
方法。像Tomcat或Jetty这样的Java web服务器也支持HTTP补丁方法吗?在这种情况下,我可以使用PUT请求,因为我正在修改资源。很抱歉,我没有概述哪个容器或框架支持
补丁
PUT
是一个好主意,但也有你需要的缺点。谢谢。为了稳定起见,我现在只使用http
PUT
,希望http
PATCH
方法将正式包含在以后的Jersey版本中。我也需要这样做,虽然在我的情况下,我实际上没有要发送的正文,但我确实需要强制发送一个“Content Length:0”和一个DELETE。在Jersey客户端2.5.2上尝试这个建议,我得到了一个ProtocolException:java.net.ProtocolException:HTTP方法DELETE不支持在org.glassfish.Jersey.Client.HttpUrlConnector$3.getOutputStream(HttpUrlConnector.java:1081)上的输出我试图将org.glassfish.jersey.test.JerseyTest#configureClient with ClientProperties.SUPPRESS_HTTP_COMPLIANCE_验证设置为true,结果失败。现在已经没有例外了,但我得到了400的服务响应。我正在将一个服务器应用程序从Play Framework转换为纯JavaEE,并且有一个包含JSON主体的删除资源。我不能只是打破旧的API,所以这对我有帮助!Jersey调用中有validateHttpMethodAndEntity函数,用于验证方法和实体的存在。这个会扔IllegalStateException@pshirishreddy,我使用JAX RS客户端API的resteasy实现。同意,但OP问题与jersey客户有关:)resteasy是jersey客户
map.put("DELETE", EntityPresence.MUST_BE_NULL);
map.put("GET", EntityPresence.MUST_BE_NULL);
...
    ClientConfig config = new ClientConfig();
    config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
    Client client = ClientBuilder.newClient(config);
    ...
client.target("$baseUrl$restEndPoint/$entityId")
                .request("application/json")
                .build("DELETE", Entity.entity(entity, MediaType.APPLICATION_JSON))
                .invoke()