JAX-RS 为 HTTP 动词(例如GET
( @GET
) 和POST
( @POST
))提供注释,但没有@PATCH
注释。如何为PATCH
HTTP 动词添加注释?
类似于以下内容:
@PATCH
public Response someCode() {
// Code to handle the request
}
我在这里得到了答案。
只需定义一个自定义 Patch 注释,这意味着您必须使用以下代码编写一个PATCH.java文件:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH {
}
导入包含 PATCH.java的包,然后您可以像使用其他 HTTP 方法注释一样使用它:
@PATCH
@Path("/data/{keyspace}")
@Produces({ "application/json" })
public void patchRow(@PathParam("keyspace") String keyspace, String body)
throws Exception
我使用这个@PATCH 将一些 JSON 发送到我的 REST 服务。
JAX-RS 2.1添加@PATCH
到支持的 HTTP 方法列表中。
在使用Swagger记录 REST API 时,您可以使用包中定义的现有@PATCH
注解io.swagger.jaxrs
。
Dropwizard在包中定义了一个@PATCH
注解。io.dropwizard.jersey
如果上述方法对您不起作用,您可以编写自己的@PATCH
注释:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH { }
注解用于将 HTTP 方法的名称与@HttpMethod
注解相关联,从而创建 JAX-RS 规范所称的资源方法指示符。
您自己的@PATCH
注释应该可以在 Swagger 中正常工作。
在 Jersey 中这可以正常工作,但是当使用 Jersey Client 测试你的资源类时,你会得到异常:
java.net.ProtocolException: Invalid HTTP method: PATCH
有一个解决方法,通过设置客户端属性
HttpUrlConnectorProvider.SET_METHOD_WORKAROUND
但是等一下,你最终会遇到以下异常:
javax.ws.rs.ProcessingException: java.net.ProtocolException: HTTP method PATCH doesn't support output
因此,除了使用 Jersey 2.10 版更改为 Apache HTTP 客户端库之外别无他法,它易于配置以使用 Apache HTTP 客户端,您只需在扩展的测试类中覆盖客户端配置方法JerseyTest
。
@Override
protected void configureClient(ClientConfig config) {
config.register(CustomJacksonJsonProvider.class);
ConnectorProvider connectorProvider = new ApacheConnectorProvider();
config.connectorProvider(connectorProvider);
}
您还需要添加另一个 Maven 依赖项,jersey-apache-connector
并且jersey-test-framework-provider-external
,请参阅Jersey 文档
JAX-RS API 2.0.1 没有 PATCH。但是,查看 JAX-RS API 2.2-SNAPSHOT 代码,现在包含 PATCH。代码是:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod(HttpMethod.PATCH)
@Documented
public @interface PATCH {
}
这是链接。
在 2.2 发布之前,您可以使用相同的代码进行补救。对于 HttpMethod.PATCH,只需将其替换为“PATCH”即可。
这是我用 jax-rs 2.2 实现的 PATCH
人物类
public class Person {
private Integer id;
@NotEmpty
@Size(min = 2)
private String name;
@NotEmpty
@Size(min = 2)
private String surname;
// getters and setters
}
人员 REST API
/**
* see https://tools.ietf.org/html/rfc6902 for further explanations
*/
@PATCH
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}")
public void modify(@PathParam("id") int id,
JsonArray input) {
personDB.update(id, input);
}
个人数据库
public void update(int id, final JsonArray input) {
final Person person = people.stream()
.filter(i -> i.getId() == id)
.findAny()
.orElseThrow(NotFoundException::new);
final JsonObject source; // json object person representation
try (JsonReader jsonReader = Json.createReader(new StringReader(Json.createValue(JsonbBuilder.create().toJson(person)).getString()))) {
source = jsonReader.readObject();
}
final JsonObject output; // apply update to source object
try {
output = Json.createPatch(input).apply(source);
} catch (JsonException e) {
throw new BadRequestException(e.getMessage());
}
try (final Jsonb jsonb = JsonbBuilder.create()) { // apply updates to final object
final Person target = jsonb.fromJson(output.toString(), Person.class);
person.setName(target.getName());
person.setSurname(target.getSurname());
} catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
测试 API:
PATCH /person/{id}
[
{
"op": "add",
"path": "/name",
"value": "John"
}
]
在这里您可以找到带有完整示例的项目
另请参阅RFC以获取更多说明
如果您使用的是 CXF 3.1.2 或更高版本(来源),则可以使用org.apache.cxf.jaxrs.ext.PATCH
.