繁体   English   中英

如何在CXF中使用PATCH方法

[英]How to use PATCH method in CXF

我正在尝试在我的客户端使用PATCH方法使用JAX-RS的CXF实现。 起初我将PATCH注释定义为

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH {
}

引用这里写的内容: 如何为JAX-RS提供@PATCH注释?

然后我发现@PATCH被添加到CXF 3.1.2中,所以我在我的maven的pom.xml中更改了版本,并且确实在package org.apache.cxf.jaxrs.ext;public @interface PATCH package org.apache.cxf.jaxrs.ext; 并且代码实际上看起来与我上面发布的完全相同。

但是,当我尝试在我的服务定义上使用此注释时

@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就像我在上面发布的queston链接中所说的那样。 他们用Jersey讨论了一些解决方案,但是我可以在CXF中做什么,以便我可以使用:

AbcService abcService = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
abcService.patchSomething(new RequestObject('something'));

所以我有几个问题:

  1. 我怎样才能做到这一点? 不,我需要编写自定义CXF拦截器?
  2. 为什么如果它不起作用,他们会将PATCH注释添加到CXF中?
  3. 另一个话题中的一些人说,提到的PATCH注释定义适用于他们。 怎么会 ? 它只会在客户端造成麻烦,如果是这样,为什么呢?
  4. 为什么我在CXF文档中找不到这个注释? 我查看了http://cxf.apache.org/javadoc/latest/上的 org.apache.cxf.jaxrs.ext包,但是我没有看到任何PATCH。 然而在最新的cxf 3.1.2中我真的可以在这个包中找到它。

事实证明这是因为在JAVA7中,HttpURLConnection不支持PATCH,该类中支持的方法被静态定义为

   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-hccxf

但是你可以看到我所描述的并没有解决原始问题,这样我只做了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,它定义了conduit属性。 然后在服务调用的后期阶段,CXF使用此属性来选择应该使用哪个Conduit实现,之后

if ( message.get(Message.HTTP_REQUEST_METHOD).equals("PATCH") {
  message.put("use.async.http.conduit", true);
}

将使用AsyncHTTPConduit实例与PATCH一起工作。

您是否可以尝试在代码中使用@PATCH替换@POST ,以查看它是否有效? 您的AbcService接口错过了类型级别的@Path注释(除非它是一个子资源?),因此首先尝试使用标准HTTP谓词来确保其他所有内容都已正确配置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM