如何在Jersey客户端的DELETE请求中发送封装数据?
我在Jersey 2.x中有以下服务器端代码:
@Path("/store/remove/from/group") @DELETE @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.TEXT_PLAIN) public Response removeStoresFromGroup(@FormParam("storeName") List storeNames, @FormParam("groupName") String groupName) { //...... }
在客户端,我想使用Jersey 2.x客户端向上述Web服务发送删除请求。 但是,从Jersey客户端API的文档中,我没有找到如何在DELETE请求中包含以下数据:
WebTarget webTarget = client.target("/store/remove/from/group"); MultivaluedMap formData = new MultivaluedHashMap(); List storeName = new ArrayList(); 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请求?
具有实体主体的DELETE
不是严格禁止的,但它非常罕见并被某些框架/服务器忽略。 实体主体的需要可能表明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
是合适的方法。 JSON-Patch是描述此类更改的良好格式。 请求看起来像这样:
PATCH /groups/4711 HTTP/1.1 Content-Type: application/json-patch [ { "op" : "remove" "path" : "stores/1" } ]
根据Jersey 2.18版本中的代码, JerseyInvocation
类使用预定义的HashMap来validationHTTP方法及其实体,如下所示:
map.put("DELETE", EntityPresence.MUST_BE_NULL); map.put("GET", EntityPresence.MUST_BE_NULL); ...
这就是为什么我们得到这个错误“对于http方法DELETE,实体必须为null”。
虽然,请注意它还提供了一个Jersey客户端配置属性ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION
来确定是否停止其余的执行,所以在这里我们可以使用此属性来禁止validation,以便继续向Entity发送DELETE
请求。 例如
ClientConfig config = new ClientConfig(); config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); Client client = ClientBuilder.newClient(config); ...
需要注意的是:如果您使用JAX RS Client API
resteasy
实现,您可以使用build().invoke()
:
client.target("$baseUrl$restEndPoint/$entityId") .request("application/json") .build("DELETE", Entity.entity(entity, MediaType.APPLICATION_JSON)) .invoke()
但它不适用于jersey
您可以使用webTarget.request().accept(MediaType.TEXT_PLAIN).method("DELETE",yourEntity)
来调用其中包含实体的DELETE
。