How to send enclose data in DELETE request in Jersey client?
我在Jersey 2.x中有以下服务器端代码:
1 2 3 4 5 6 7
| @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客户端API的文档中,我没有找到如何在DELETE请求中包含以下数据:
1 2 3 4 5 6 7 8 9 10 11
| 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):
1
| Response response = webTarget. request(). accept(MediaType. TEXT_PLAIN). post(Entity. form(formData )); |
但我想使用DELETE请求,因为请求正在删除一些资源。 如何通过Jersey客户端发送带有一些实体数据的DELETE请求?
-
OT但通常您不需要发送带有DELETE的实体,因为"DELETE方法请求源服务器删除Request-URI标识的资源"。 您的方法引用听起来更像是更新引用然后删除资源。
-
有时如果我想删除一些满足某些条件的数据,我需要在DELETE请求的实体主体中传入一些参数。
基于Jersey 2.18版本中的代码,类JerseyInvocation使用预定义的HashMap来验证HTTP方法及其实体,如下所示:
1 2 3
| map.put("DELETE", EntityPresence.MUST_BE_NULL);
map.put("GET", EntityPresence.MUST_BE_NULL);
... |
这就是为什么我们得到这个错误"对于http方法DELETE,实体必须为null"。
虽然,请注意它还提供了一个泽西岛客户端配置属性ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION来确定是否停止其余的执行,所以在这里我们可以使用此属性来禁止验证,以便继续发送带有实体的DELETE请求。例如
1 2 3 4
| ClientConfig config = new ClientConfig();
config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Client client = ClientBuilder.newClient(config);
... |
-
我有类似的需要这样做,虽然在我的情况下我实际上没有要发送的主体,但我确实需要强制使用DELETE发送'Content-Length:0'。尝试使用Jersey Client 2.5.2的这个建议,我得到一个ProtocolException:java.net.ProtocolException:HTTP方法DELETE不支持sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1081)的输出在org.glassfish.jersey.client.HttpUrlConnector $ 3.getOutputStream(HttpUrlConnector.java:267)
-
我尝试将ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION设置为true的org.glassfish.jersey.test.JerseyTest #configureClient重置为失败。没有例外,但我得到了400的服务响应。
-
我正在将服务器应用程序从Play Framework转换为纯JavaEE,并且有一个带有JSON主体的DELETE资源。我不能打破旧的API,这对我有帮助!
需要注意的是:如果您使用resteasy JAX RS Client API的实现,则可以使用build().invoke():
1 2 3 4
| client. target("$baseUrl$restEndPoint/$entityId")
. request("application/json")
. build("DELETE", Entity. entity(entity, MediaType. APPLICATION_JSON))
. invoke() |
但它不适用于jersey
-
JerseyInvocation中有validateHttpMethodAndEntity函数,用于验证方法和实体的存在。这将抛出IllegalStateException
-
@pshirishreddy,我使用JAX RS Client API的重新实现。它有效。
-
同意但OP问题与球衣客户有关:)
具有实体主体的DELETE不是严格禁止的,但它非常罕见并被某些框架/服务器忽略。实体主体的需要可以指示DELETE未按预期使用。
例如:如果GET /customers/4711返回一个客户并且您发送DELETE /customers/4711,则此资源上的下一个GET应返回404。您删除了由规范中定义的URL标识的资源。
您的网址/store/remove/from/group似乎无法识别资源。使用/store/4711或/groups/4711之类的标识符并在其上发送DELETE将无法满足您的需求,因为您希望"从组中删除商店"而不是删除商店或组。
假设您有一个组资源
1 2 3 4
| {
"id" : 4711,
"stores" : [123, 456, 789]
} |
你想要一个像这样的结果
1 2 3 4
| {
"id" : 4711,
"stores" : [123, 789]
} |
你没有删除任何东西。您正在修改资源,因此PUT,POST或PATCH是合适的方法。 JSON-Patch是描述此类更改的良好格式。请求看起来像这样:
1 2 3 4 5 6 7 8 9
| PATCH /groups/4711 HTTP/1.1
Content-Type: application/json-patch
[
{
"op" :"remove"
"path" :"stores/1"
}
] |
-
谢谢你的建议。似乎Jersey框架目前不支持PATCH方法。像Tomcat或Jetty这样的Java Web服务器是否也支持HTTP PATCH方法?在这种情况下,我可以使用PUT请求,因为我正在修改资源。
-
对不起,我没有概述哪个容器或框架支持PATCH。 PUT是一个好主意,但这有一个缺点,你需要发送整个修改过的资源。
-
谢谢。为了稳定起见,我现在只使用http PUT,希望http PATCH方法将正式包含在后来的Jersey版本中。
您可以使用webTarget.request().accept(MediaType.TEXT_PLAIN).method("DELETE",yourEntity)调用其中包含实体的DELETE。
-
当我使用此方法时,它报告错误:"对于http方法DELETE,实体必须为null"。这是为什么?
-
嗯,老实说我没想到。如果你看一下第9.6节的[1],你会发现DELETE是基于URI的。它并没有说它不能使用身体.. [1]:w3.org/Protocols/rfc2616/rfc2616-sec9.html
-
我不明白为什么DELETE请求不能包含来自doc的实体主体。但是javadoc(docs.oracle.com/javaee/7/api/javax/ws/rs/client/…)并没有说它也不能使用DELETE作为方法名称。