http://localhost:8080/hello
WebFlux REST API と WebClient
このガイドでは、Spring WebFlux (Spring Boot 2.0 の新機能) を使用して "Hello, Spring!" RESTful Web サービスを作成し、WebClient (これも Spring Boot 2.0 の新機能) を使用してそのサービスを使用するプロセスについて説明します。
このガイドでは、Spring WebFlux の関数使用方法を示します。WebFlux でアノテーションを使用することもできます。 |
構築するもの
Spring Webflux とそのサービスの WebClient コンシューマーを使用して RESTfulWeb サービスを構築します。System.out と次の両方で出力を確認できます。
必要なもの
約 15 分
Eclipse STS や IntelliJ IDEA のような任意の IDE または VSCode のようなテキストエディター
Java 17 以降
コードを直接 IDE にインポートすることもできます。
本ガイドの完成までの流れ
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドを Eclipse で「Spring 入門コンテンツのインポート」するか、ソースリポジトリをダウンロードして解凍、または、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-reactive-rest-service.git
gs-reactive-rest-service/initial
に cdWebFlux ハンドラーを作成するにジャンプしてください。
完了したときは、gs-reactive-rest-service/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。
プロジェクトを手動で初期化するには:
IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。
Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。
依存関係をクリックして、Spring リアクティブ Web を選択します。
生成をクリックします。
結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。
Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。 |
プロジェクトを Github からフォークして、IDE または他のエディターで開くこともできます。 |
WebFlux ハンドラーを作成する
まず、RESTful サービスによって JSON として直列化される Greeting
POJO から始めます。
src/main/java/hello/Greeting.java
package com.example.reactivewebservice;
public class Greeting {
private String message;
public Greeting() {
}
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "Greeting{" +
"message='" + message + '\'' +
'}';
}
}
Spring のリアクティブアプローチでは、次の例に示すように、ハンドラーを使用してリクエストを処理し、レスポンスを作成します。
src/main/java/hello/GreetingHandler.java
package com.example.reactivewebservice;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
@Component
public class GreetingHandler {
public Mono<ServerResponse> hello(ServerRequest request) {
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(new Greeting("Hello, Spring!")));
}
}
この単純なリアクティブクラスは、常に「Hello、Spring!」の JSON 本文を返します。挨拶。データベースからのアイテムのストリーム、計算によって生成されたアイテムのストリームなど、他の多くのものを返す可能性があります。リアクティブコードに注意してください。ServerResponse
本体を保持する Mono
オブジェクトです。
ルーターを作成する
このアプリケーションでは、次の例に示すように、ルーターを使用して、公開する唯一のルート(/hello
)を処理します。
src/main/java/hello/GreetingRouter.java
package com.example.reactivewebservice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
@Configuration(proxyBeanMethods = false)
public class GreetingRouter {
@Bean
public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {
return RouterFunctions
.route(GET("/hello").and(accept(MediaType.APPLICATION_JSON)), greetingHandler::hello);
}
}
ルーターは /hello
パスでトラフィックをリッスンし、リアクティブハンドラークラスによって提供された値を返します。
WebClient を作成する
Spring RestTemplate
クラスは、本質的にブロッキングです。リアクティブアプリケーションでは使用したくありません。リアクティブアプリケーションの場合、Spring はノンブロッキングである WebClient
クラスを提供します。WebClient ベースの実装を使用して、RESTful サービスを利用します。
src/main/java/hello/GreetingClient.java
package com.example.reactivewebservice;
import reactor.core.publisher.Mono;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
@Component
public class GreetingClient {
private final WebClient client;
// Spring Boot auto-configures a `WebClient.Builder` instance with nice defaults and customizations.
// We can use it to create a dedicated `WebClient` for our component.
public GreetingClient(WebClient.Builder builder) {
this.client = builder.baseUrl("http://localhost:8080").build();
}
public Mono<String> getMessage() {
return this.client.get().uri("/hello").accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(Greeting.class)
.map(Greeting::getMessage);
}
}
WebClient
クラスは、Mono
の形式でリアクティブ機能を使用して、メッセージのコンテンツを保持します(getMessage
メソッドによって返されます)。これは、チェーンリアクティブ演算子に対して、命令型ではなく関数 API を使用しています。
リアクティブ API に慣れるまでには時間がかかる場合がありますが、WebClient
には興味深い機能があり、従来の Spring MVC アプリケーションでも使用できます。
WebClient を使用して、非リアクティブのブロッキングサービスと通信することもできます。 |
アプリケーションを実行可能にする
main()
メソッドを使用してアプリケーションを駆動し、エンドポイントからグリーティングメッセージを取得します。
src/main/java/hello/Application.java
package com.example.reactivewebservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class ReactiveWebServiceApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ReactiveWebServiceApplication.class, args);
GreetingClient greetingClient = context.getBean(GreetingClient.class);
// We need to block for the content here or the JVM might exit before the message is logged
System.out.println(">> message = " + greetingClient.getMessage().block());
}
}
@SpringBootApplication
は、次のすべてを追加する便利なアノテーションです。
@Configuration
: アプリケーションコンテキストの Bean 定義のソースとしてクラスにタグを付けます。@EnableAutoConfiguration
: クラスパス設定、他の Bean、さまざまなプロパティ設定に基づいて Bean の追加を開始するよう Spring Boot に指示します。例:spring-webmvc
がクラスパスにある場合、このアノテーションはアプリケーションに Web アプリケーションとしてフラグを立て、DispatcherServlet
のセットアップなどの主要な動作をアクティブにします。@ComponentScan
: Spring に、hello
パッケージ内の他のコンポーネント、構成、サービスを探して、コントローラーを検出させるように指示します。
main()
メソッドは、Spring Boot の SpringApplication.run()
メソッドを使用してアプリケーションを起動します。XML が 1 行もないことに気付きましたか? web.xml
ファイルもありません。この Web アプリケーションは 100% 純粋な Java であり、接続機能やインフラストラクチャの構成に対処する必要はありませんでした。
実行可能 JAR を構築する
コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。
Gradle を使用する場合、./gradlew bootRun
を使用してアプリケーションを実行できます。または、次のように、./gradlew build
を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。
Maven を使用する場合、./mvnw spring-boot:run
を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package
で JAR ファイルをビルドしてから、JAR ファイルを実行できます。
ここで説明する手順は、実行可能な JAR を作成します。クラシック WAR ファイルを作成することもできます。 |
ロギング出力が表示されます。サービスは数秒以内に起動して実行されるはずです。
サービスが開始されると、次のような行が表示されます。
>> message = Hello, Spring!
その行は、WebClient によって消費されるリアクティブコンテンツに由来しています。当然、System.out に出力するよりも、出力で行う方が面白いものを見つけることができます。
アプリケーションをテストする
アプリケーションが実行されているため、テストできます。まず、ブラウザーを開いて http://localhost:8080/hello
に移動し、「こんにちは、Spring!」と表示します。このガイドでは、WebTestClient
クラスのテストを開始するためのテストクラスも作成しました。
src/test/java/hello/GreetingRouterTest.java
package com.example.reactivewebservice;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
// We create a `@SpringBootTest`, starting an actual server on a `RANDOM_PORT`
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GreetingRouterTest {
// Spring Boot will create a `WebTestClient` for you,
// already configure and ready to issue requests against "localhost:RANDOM_PORT"
@Autowired
private WebTestClient webTestClient;
@Test
public void testHello() {
webTestClient
// Create a GET request to test an endpoint
.get().uri("/hello")
.accept(MediaType.APPLICATION_JSON)
.exchange()
// and use the dedicated DSL to test assertions against the response
.expectStatus().isOk()
.expectBody(Greeting.class).value(greeting -> {
assertThat(greeting.getMessage()).isEqualTo("Hello, Spring!");
});
}
}
要約
おめでとう! RESTful サービスを使用する WebClient を含む Reactive Spring アプリケーションを開発しました!
新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語) 。
すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives creative commons ライセンス (英語) でリリースされています。 |