如何在CXF中使用PATCH方法
How to use PATCH method in CXF
我正在尝试在使用 JAX-RS 的 CXF 实现的客户端中使用 PATCH 方法。
一开始我把PATCH注解定义为
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH {
}
引用此处所写的内容:
How to have a @PATCH annotation for JAX-RS?
然后我发现@PATCH被添加到CXF 3.1.2中,所以我在我的maven的pom.xml中更改了版本并且确实在package org.apache.cxf.jaxrs.ext;
和代码中有public @interface PATCH
实际上看起来和我上面发布的完全一样。
但是,当我尝试在我的服务定义中使用此注释时
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface AbcService {
@PATCH
@Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
我最终得到 java.net.ProtocolException: Invalid HTTP method: PATCH
正如我在上面发布的问题 link 中所说的那样。他们与 Jersey 讨论了一些解决方案,但是我可以在 CXF 中做什么,以便我可以使用:
AbcService abcService = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
abcService.patchSomething(new RequestObject('something'));
所以我有几个问题:
- 我怎样才能完成这项工作?不,我需要编写自定义 CXF 拦截器吗?
- 如果它不起作用,为什么他们将 PATCH 注释添加到 CXF 中?
- 其他主题中的一些人说提到的 PATCH 注释定义对他们有用。怎么会 ?它是否只会在客户端造成麻烦,如果是,为什么会这样?
- 为什么我在 CXF 文档中找不到这个注释?我查看了 http://cxf.apache.org/javadoc/latest/ 的 org.apache.cxf.jaxrs.ext 包,但没有看到任何 PATCH。然而在最新的cxf 3.1.2中我真的可以在这个包中找到它。
您能否尝试在您的代码中将 @PATCH
的使用替换为 @POST
以查看它是否有效?您的 AbcService
接口缺少类型级别的 @Path
注释(除非它是子资源?),因此可能值得首先尝试使用标准 HTTP 动词以确保其他所有内容都已正确配置。
原来是因为在JAVA7中,HttpURLConnection不支持PATCH,class中支持的方法静态定义为
private static final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
};
然而,可以在 CXF 中发送 PATCH 请求,但 Conduit 对象必须是 AsyncHTTPConduit
类型。
要使 CXF 使用 AsyncHTTPConduit,您可以像这样以编程方式实现它
AbcService service = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
WebClient.getConfig(service).getRequestContext().put("use.async.http.conduit", true);
service.patchEnvironmentParameters(patchRequest);
或
WebClient client = WebClient.create("http://localhost:53261/v1-0/api/environment/parameters");
WebClient.getConfig(client).getRequestContext().put("use.async.http.conduit", true);
client.invoke("PATCH", "{}");
但是要小心!!为了使这项工作正常进行,您已将此依赖项放入您的项目中
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-hc</artifactId>
<version>${cxf.version}</version>
</dependency>
还要确保您使用相同版本的 cxf-rt-transports-http-hc
和 cxf
。
但是如您所见,我所描述的内容并没有解决原始问题,因此我只提出了 1 个特定的 PATCH 请求。然而,在我的项目中,有许多 PATCH 服务使用我最初展示的接口定义
public interface AbcService {
@PATCH
@Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
因此,为了仅在 PATCH 方法上使用 AsyncHTTPConduit,我必须编写自定义 CXF 拦截器,您可以在此处了解更多信息 http://cxf.apache.org/docs/interceptors.html
我编写的拦截器在 PRE_LOGIC 阶段运行,它检查使用了哪种方法,如果是 PATCH,它定义了管道 属性。然后在服务调用的后期阶段,CXF 使用此 属性 来选择应该使用哪个 Conduit 实现,因此在
之后
if ( message.get(Message.HTTP_REQUEST_METHOD).equals("PATCH") {
message.put("use.async.http.conduit", true);
}
AsyncHTTPConduit
实例将与 PATCH 一起工作。
我正在尝试在使用 JAX-RS 的 CXF 实现的客户端中使用 PATCH 方法。 一开始我把PATCH注解定义为
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH {
}
引用此处所写的内容: How to have a @PATCH annotation for JAX-RS?
然后我发现@PATCH被添加到CXF 3.1.2中,所以我在我的maven的pom.xml中更改了版本并且确实在package org.apache.cxf.jaxrs.ext;
和代码中有public @interface PATCH
实际上看起来和我上面发布的完全一样。
但是,当我尝试在我的服务定义中使用此注释时
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface AbcService {
@PATCH
@Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
我最终得到 java.net.ProtocolException: Invalid HTTP method: PATCH
正如我在上面发布的问题 link 中所说的那样。他们与 Jersey 讨论了一些解决方案,但是我可以在 CXF 中做什么,以便我可以使用:
AbcService abcService = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
abcService.patchSomething(new RequestObject('something'));
所以我有几个问题:
- 我怎样才能完成这项工作?不,我需要编写自定义 CXF 拦截器吗?
- 如果它不起作用,为什么他们将 PATCH 注释添加到 CXF 中?
- 其他主题中的一些人说提到的 PATCH 注释定义对他们有用。怎么会 ?它是否只会在客户端造成麻烦,如果是,为什么会这样?
- 为什么我在 CXF 文档中找不到这个注释?我查看了 http://cxf.apache.org/javadoc/latest/ 的 org.apache.cxf.jaxrs.ext 包,但没有看到任何 PATCH。然而在最新的cxf 3.1.2中我真的可以在这个包中找到它。
您能否尝试在您的代码中将 @PATCH
的使用替换为 @POST
以查看它是否有效?您的 AbcService
接口缺少类型级别的 @Path
注释(除非它是子资源?),因此可能值得首先尝试使用标准 HTTP 动词以确保其他所有内容都已正确配置。
原来是因为在JAVA7中,HttpURLConnection不支持PATCH,class中支持的方法静态定义为
private static final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
};
然而,可以在 CXF 中发送 PATCH 请求,但 Conduit 对象必须是 AsyncHTTPConduit
类型。
要使 CXF 使用 AsyncHTTPConduit,您可以像这样以编程方式实现它
AbcService service = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
WebClient.getConfig(service).getRequestContext().put("use.async.http.conduit", true);
service.patchEnvironmentParameters(patchRequest);
或
WebClient client = WebClient.create("http://localhost:53261/v1-0/api/environment/parameters");
WebClient.getConfig(client).getRequestContext().put("use.async.http.conduit", true);
client.invoke("PATCH", "{}");
但是要小心!!为了使这项工作正常进行,您已将此依赖项放入您的项目中
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-hc</artifactId>
<version>${cxf.version}</version>
</dependency>
还要确保您使用相同版本的 cxf-rt-transports-http-hc
和 cxf
。
但是如您所见,我所描述的内容并没有解决原始问题,因此我只提出了 1 个特定的 PATCH 请求。然而,在我的项目中,有许多 PATCH 服务使用我最初展示的接口定义
public interface AbcService {
@PATCH
@Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
因此,为了仅在 PATCH 方法上使用 AsyncHTTPConduit,我必须编写自定义 CXF 拦截器,您可以在此处了解更多信息 http://cxf.apache.org/docs/interceptors.html 我编写的拦截器在 PRE_LOGIC 阶段运行,它检查使用了哪种方法,如果是 PATCH,它定义了管道 属性。然后在服务调用的后期阶段,CXF 使用此 属性 来选择应该使用哪个 Conduit 实现,因此在
之后if ( message.get(Message.HTTP_REQUEST_METHOD).equals("PATCH") {
message.put("use.async.http.conduit", true);
}
AsyncHTTPConduit
实例将与 PATCH 一起工作。