Spring RestTemplateインターセプターの使用

1概要

このチュートリアルでは、Springリンクの実装方法を学びます:/rest-template __ __Interceptor。

応答にカスタムヘッダーを追加するインターセプターを作成する例を見ていきます。

2.インターセプターの使用シナリオ

ヘッダーの修正の他に、 RestTemplate インターセプターが役立つ他のユースケースのいくつかは以下のとおりです。

  • リクエストとレスポンスのロギング

  • 設定可能なバックオフ戦略でリクエストを再試行する

  • 特定のリクエストパラメータに基づくリクエスト拒否

  • リクエストURLアドレスを変更する

3インターセプターの作成

ほとんどのプログラミングパラダイムでは、インターセプタはプログラマーが実行をインターセプトすることによって実行を制御することを可能にする重要な部分です。

Spring RestTemplate では、https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/client/ClientHttpRequestInterceptor.html[ ClientHttpRequestInterceptor ]インターフェースを実装するインターセプターを追加することができます。このインタフェースの intercept(HttpRequest、byte[]、ClientHttpRequestExecution) メソッドは、指定された要求をインターセプトし、 request body 、および execution オブジェクトへのアクセスを許可することによって応答を返します。

実際に実行するために ClientHttpRequestExecution 引数を使用して、リクエストを後続のプロセスチェーンに渡します。

  • 最初のステップとして、 ClientHttpRequestInterceptor インターフェースを実装するインターセプタークラスを作成しましょう:**

public class RestTemplateHeaderModifierInterceptor
  implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(
      HttpRequest request,
      byte[]body,
      ClientHttpRequestExecution execution) throws IOException {

        ClientHttpResponse response = execution.execute(request, body);
        response.getHeaders().add("Foo", "bar");
        return response;
    }
}
  • 私たちのインターセプターはすべての入ってくる要求のために呼び出されます** 、そしてそれは実行が完了して戻ると、すべての応答にカスタムヘッダー Foo を追加します。

intercept() メソッドには引数として request body が含まれているため、リクエストを変更したり、特定の条件に基づいてリクエストの実行を拒否することもできます。

4 RestTemplate を設定する

インターセプターを作成したので、 RestTemplate Beanを作成し、それにインターセプターを追加しましょう。

@Configuration
public class RestClientConfig {

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        List<ClientHttpRequestInterceptor> interceptors
          = restTemplate.getInterceptors();
        if (CollectionUtils.isEmpty(interceptors)) {
            interceptors = new ArrayList<>();
        }
        interceptors.add(new RestTemplateHeaderModifierInterceptor());
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    }
}

場合によっては、 RestTemplate オブジェクトに既にインターセプターが追加されている可能性があります。したがって、すべてが期待どおりに機能することを確認するために、私たちのコードはインターセプターリストが空の場合にのみ初期化します。

コードが示すように、 RestTemplate オブジェクトを作成するためにデフォルトのコンストラクターを使用していますが、要求/応答ストリームを2回読み取る必要があるシナリオがいくつかあります。

たとえば、インターセプターを要求/応答ロガーとして機能させたい場合は、インターセプターが1回目とクライアントが2回目という2回読み取る必要があります。

デフォルトの実装では、レスポンスストリームを一度だけ読み込むことができます。そのような特定のシナリオに応えるために、Springは__BufferingClientHttpRequestFactoryという特別なクラスを提供します。名前が示すように、このクラスは複数の使用のためにJVMメモリでリクエスト/レスポンスをバッファします。

これは、リクエスト/レスポンスストリームのキャッシュを有効にするために BufferingClientHttpRequestFactory を使用して RestTemplate オブジェクトを初期化する方法です。

RestTemplate restTemplate
  = new RestTemplate(
    new BufferingClientHttpRequestFactory(
      new SimpleClientHttpRequestFactory()
    )
  );

5例をテストする

これが私たちの RestTemplate インターセプターをテストするためのJUnitテストケースです:

public class RestTemplateItegrationTest {

    @Autowired
    RestTemplate restTemplate;

    @Test
    public void givenRestTemplate__whenRequested__thenLogAndModifyResponse() {
        LoginForm loginForm = new LoginForm("username", "password");
        HttpEntity<LoginForm> requestEntity
          = new HttpEntity<LoginForm>(loginForm);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION__JSON);

        ResponseEntity<String> responseEntity
          = restTemplate.postForEntity(
            "http://httpbin.org/post", requestEntity, String.class
          );

        assertThat(
          responseEntity.getStatusCode(),
          is(equalTo(HttpStatus.OK))
        );
        assertThat(
          responseEntity.getHeaders().get("Foo").get(0),
          is(equalTo("bar"))
        );
    }
}

ここでは、データを投稿するために、無料でホストされているHTTPリクエスト/レスポンスサービスhttp://httpbin.org を使用しました。このテストサービスは、いくつかのメタデータと共にリクエストボディを返します。

6. 結論

このチュートリアルでは、インターセプターを設定してそれを RestTemplate オブジェクトに追加する方法について説明します。この種のインターセプターは、着信要求のフィルタリング、監視、および制御にも使用できます。

RestTemplate インターセプターの一般的なユースケースは、ヘッダーの変更です。これについては、この記事で詳しく説明します。

そして、いつものように、あなたはhttps://github.com/eugenp/tutorials/tree/master/spring-rest[Github project]でサンプルコードを見つけることができます。これはMavenベースのプロジェクトなので、そのままインポートして実行するのは簡単なはずです。