5

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 のバージョンを変更しました。実際にはそこpublic @interface PATCHpackage 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投稿した質問のリンクで述べたようになります。彼らはこれに対するいくつかの解決策を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 では、このパッケージで実際に見つけることができます。
4

2 に答える 2

8

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-hcとを使用していることを確認してくださいcxf

しかし、私が説明したことは元の問題を解決しないことがわかるように、この方法で 1 つの特定の PATCH 要求を作成しました。ただし、私のプロジェクトには、最初に示したようなインターフェイスを使用して定義された多くの PATCH サービスがあります

public interface AbcService {

    @PATCH
    @Path("/abc/efg")
    public SomeDTO patchSomething(RequestObject request);
}

そのため、AsyncHTTPConduit を PATCH メソッドでのみ使用するには、カスタム 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);
}

PATCH が機能するAsyncHTTPConduitインスタンスが使用されます。

于 2015-08-21T12:47:19.413 に答える