我在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请求?
答案 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 forbidden的DELETE
,但它非常罕见并被某些框架/服务器忽略。实体主体的需要可能表明未按预期使用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]
}
你没有删除任何东西。您正在修改资源,因此PUT
,POST
或PATCH
是合适的方法。 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()等“不允许”的复杂场景非常有用