開発者ドキュメント

Spring 5 Webクライアント


1概要

この記事では、Spring 5で導入されているリアクティブWebクライアントである

WebClient

を紹介します。

私たちは

WebTestClient

も見てみるつもりです – これはテストで使われるように設計された

WebClient

です。


2

WebClient

とは何ですか?

簡単に言えば、

WebClient

はWeb要求を実行するための主要なエントリポイントを表すインタフェースです。

これはSpring Web Reactiveモジュールの一部として作成されており、これらのシナリオでは従来の

RestTemplate

に代わるものとなるでしょう。新しいクライアントは、HTTP/1.1プロトコル上で機能する、反応性のある非ブロッキングソリューションです。

最後に、このインターフェースには

DefaultWebClient

クラスという単一の実装があり、それを処理します。


3依存関係

Spring Bootアプリケーションを使用しているので、https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter-webflux%22%20AND%20g%3Aが必要です。 %22org.springframework.boot%22[

spring-boot-starter-webflux

]依存関係、およびhttp://repo1.maven.org/maven2/org/projectreactor/reactor-spring/[Reactorプロジェクト]。


3.1. Mavenを使った構築


pom.xml

ファイルに次の依存関係を追加しましょう。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.projectreactor</groupId>
    <artifactId>reactor-spring</artifactId>
    <version>1.0.1.RELEASE</version>
</dependency>


3.2. Gradleを使った構築

Gradleでは、

build.gradle

ファイルに次のエントリを追加する必要があります。

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-webflux'
    compile 'org.projectreactor:reactor-spring:1.0.1.RELEASE'
}


4

WebClient


を使った作業

クライアントと正しく連携するには、以下の方法を知っておく必要があります。

  • インスタンスを作成する

  • リクエストする

  • 応答を処理する


4.1.

WebClient

インスタンスを作成する

から選択する3つのオプションがあります。 1つ目は、デフォルト設定で

WebClient

オブジェクトを作成することです。

WebClient client1 = WebClient.create();

2番目の方法では、指定されたベースURIを使って

WebClient

インスタンスを起動することができます。

WebClient client2 = WebClient.create("http://localhost:8080");

最後の方法(そして最も高度な方法)は

DefaultWebClientBuilder

クラスを使ってクライアントを構築することです。

WebClient client3 = WebClient
  .builder()
    .baseUrl("https://localhost:8080")
    .defaultCookie("cookieKey", "cookieValue")
    .defaultHeader(HttpHeaders.CONTENT__TYPE, MediaType.APPLICATION__JSON__VALUE)
    .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080"))
  .build();


4.2. リクエストを準備する

まず、

method(HttpMethodメソッド)

を呼び出すか、

get



post



delete

などのショートカットメソッドを呼び出して、要求のHTTPメソッドを指定する必要があります。

WebClient.UriSpec<WebClient.RequestBodySpec> request1 = client3.method(HttpMethod.POST);
WebClient.UriSpec<WebClient.RequestBodySpec> request2 = client3.post();

次の動きはURLを提供することです。それを

String

または

java.net.URL

インスタンスとして

uri

APIに渡すことができます。

WebClient.RequestBodySpec uri1 = client3
  .method(HttpMethod.POST)
  .uri("/resource");

WebClient.RequestBodySpec uri2 = client3
  .post()
  .uri(URI.create("/resource"));

続けて、必要に応じて、リクエストボディ、コンテンツタイプ、長さ、Cookie、またはヘッダーを設定できます。

例えば、リクエストボディを設定したい場合 – 2つの利用可能な方法があります – それを

BodyInserter

で満たすか、この仕事を

Publisher

に委任する:

WebClient.RequestHeadersSpec requestSpec1 = WebClient
  .create()
  .method(HttpMethod.POST)
  .uri("/resource")
  .body(BodyInserters.fromPublisher(Mono.just("data")), String.class);

WebClient.RequestHeadersSpec<?> requestSpec2 = WebClient
  .create("http://localhost:8080")
  .post()
  .uri(URI.create("/resource"))
  .body(BodyInserters.fromObject("data"));

  • BodyInserter

    は、

    ReactiveHttpOutputMessage

    bodyに挿入時に使用される指定された出力メッセージとコンテキストを入力する役割を果たします。

2番目の方法は

body

メソッドです。これは元の

body(BodyInserter inserter)

メソッドのショートカットです。


BodyInserterを埋めるこのプロセスを軽減するために、

BodyInserters__クラスがあり、これは便利なユーティリティーメソッドの集まりです。

BodyInserter<Publisher<String>, ReactiveHttpOutputMessage> inserter1 = BodyInserters
  .fromPublisher(Subscriber::onComplete, String.class);


MultiValueMap

でも可能です。

LinkedMultiValueMap map = new LinkedMultiValueMap();

map.add("key1", "value1");
map.add("key2", "value2");

BodyInserter<MultiValueMap, ClientHttpRequest> inserter2
 = BodyInserters.fromMultipartData(map);

あるいは単一のオブジェクトを使用することによって:

BodyInserter<Object, ReactiveHttpOutputMessage> inserter3
 = BodyInserters.fromObject(new Object());

本文を設定したら、ヘッダー、Cookie、使用可能なメディアの種類を設定できます。クライアントをインスタンス化するときに設定された値に値が追加されます。

また、__「If-None-Match」、「If-Modified-Since」、「Accept」、「Accept-Charset」など、最も一般的に使用されるヘッダーの追加サポート

これらの値を使用する方法の例を次に示します。

WebClient.ResponseSpec response1 = uri1
  .body(inserter3)
    .header(HttpHeaders.CONTENT__TYPE, MediaType.APPLICATION__JSON__VALUE)
    .accept(MediaType.APPLICATION__JSON, MediaType.APPLICATION__XML)
    .acceptCharset(Charset.forName("UTF-8"))
    .ifNoneMatch("** ")
    .ifModifiedSince(ZonedDateTime.now())
  .retrieve();


4.3. 回答を得る

最後の段階は、要求を送信して応答を受信することです。これは、

exchange

メソッドまたは

retrieve

メソッドのどちらでも実行できます。

それらは戻り型が異なります。

exchange

メソッドはステータス、ヘッダとともに

ClientResponse

を提供し、

retrieve

メソッドはボディを直接取得するための最短パスです。

String response2 = request1.exchange()
  .block()
  .bodyToMono(String.class)
  .block();
String response3 = request2
  .retrieve()
  .bodyToMono(String.class)
  .block();


bodyToMono

メソッドに注意してください。ステータスコードが

4xx

(クライアントエラー)または

5xx

(サーバーエラー)の場​​合は、

WebClientException

がスローされます。応答とともに送信された実際のデータをサブスクライブして取得するために、

__Mon


sで

block__メソッドを使用しました。


5

WebTestClient


を使った作業


WebTestClient

はWebFluxサーバーエンドポイントをテストするための主要なエントリポイントです。これは

WebClient

と非常によく似たAPIを持ち、主にテストコンテキストの提供に焦点を合わせて、ほとんどの作業を内部の

WebClient

インスタンスに委任しています。

DefaultWebTestClient

クラスは単一のインターフェイス実装です。

テスト用のクライアントは、実サーバーにバインドすることも、特定のコントローラーや機能を処理することもできます。実行中のサーバーへの実際のリクエストでエンドツーエンドの統合テストを完了するには、

bindToServer

メソッドを使用できます。

WebTestClient testClient = WebTestClient
  .bindToServer()
  .baseUrl("https://localhost:8080")
  .build();

特定の

RouterFunction



bindToRouterFunction

メソッドに渡すことでテストできます。

RouterFunction function = RouterFunctions.route(
  RequestPredicates.GET("/resource"),
  request -> ServerResponse.ok().build()
);

WebTestClient
  .bindToRouterFunction(function)
  .build().get().uri("/resource")
  .exchange()
  .expectStatus().isOk()
  .expectBody().isEmpty();


WebHandler

インスタンスをとる

bindToWebHandler

メソッドを使用しても同じ動作を実現できます。

WebHandler handler = exchange -> Mono.empty();
WebTestClient.bindToWebHandler(handler).build();


bindToApplicationContext

メソッドを使用していると、さらに興味深い状況が発生します。それは

ApplicationContext

を取り、コントローラBeanのコンテキストと

@ EnableWebFlux

設定を分析します。


ApplicationContext

のインスタンスを挿入すると、単純なコードスニペットは次のようになります。

@Autowired
private ApplicationContext context;

WebTestClient testClient = WebTestClient.bindToApplicationContext(context)
  .build();

もっと短いアプローチは

bindToController

メソッドでテストしたいコントローラーの配列を提供することです。

Controller

クラスを取得し、それを必要なクラスにインジェクトしたと仮定すると、次のように書くことができます。

@Autowired
private Controller controller;

WebTestClient testClient = WebTestClient.bindToController(controller).build();


WebTestClient

オブジェクトを構築した後は、チェーン内の以降のすべての操作は、

exchangeStメソッドのような

WebTestClient.ResponseSpec

インターフェースを提供する

exchange

メソッドまでの

WebClient

に似たものになります。

expectBody



expectHeader__:

WebTestClient
  .bindToServer()
    .baseUrl("https://localhost:8080")
    .build()
    .post()
    .uri("/resource")
  .exchange()
    .expectStatus().isCreated()
    .expectHeader().valueEquals("Content-Type", "application/json")
    .expectBody().isEmpty();


6. 結論

このチュートリアルでは、クライアント側でリクエストを行うための新しい強化されたSpringメカニズム、つまり

WebClient

クラスについて説明しました。

また、リクエスト処理を通じてすべての利点を提供しています。

この記事に記載されているすべてのコードスニペットは、https://github.com/eugenp/tutorials/tree/master/spring-5-reactive[私たちのGitHubレポジトリ]にあります。

モバイルバージョンを終了