Spring 5の機能的Webフレームワークの紹介
1前書き
Spring WebFluxフレームワークは反応原理を使って構築された新しい機能的Webフレームワークを導入します
このチュートリアルでは、このフレームワークを実際に使用する方法を学びます。
これは、既存のチュートリアルhttps://www.baeldung.com/spring-webflux[Spring 5 WebFluxのガイド]に基づいています。そのガイドでは、Annotationベースのコンポーネントを使用して小さなリアクティブRESTアプリケーションを作成しました。ここでは、代わりに機能的フレームワークを使用します。
2 Mavenの依存関係
同じ依存関係が必要です。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]:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
3機能的Webフレームワーク
機能的Webフレームワークは、リクエストをルーティングし処理するために関数を使用する新しいプログラミングモデルを導入します。
アノテーションマッピングを使用するアノテーションベースのモデルとは対照的に、ここではhttp://docs.spring.io/spring/docs/5.0.0.M5/javadoc-api/org/springframework/web/reactiveを使用します。/function/server/HandlerFunction.html[
HandlerFunction
]および
http://docs.spring.io/spring/docs/5.0.0.M5/javadoc-api/org/springframework/web/reactive/function/server/RouterFunction。
html[RouterFunctions]
。
また、機能的Webフレームワークは、注釈ベースのリアクティブフレームワークが構築されたのと同じリアクティブスタック上に構築されます。
3.1. HandlerFunction
HandlerFunction
は、それらにルーティングされた要求に対する応答を生成する関数を表します。
@FunctionalInterface
public interface HandlerFunction<T extends ServerResponse> {
Mono<T> handle(ServerRequest request);
}
このインタフェースは主に
Function <Request、Response <T>>
であり、サーブレットのように動作します。
ただし、標準のサーブレット
Servlet.service(ServletRequest req、ServletResponse res)
と比較すると、
HandlerFunction
は、応答を無料にしてテストおよび再利用を容易にするパラメータとして受け取る代わりに、応答を返します。
3.2.
RouterFunction
RouterFunction
は、@ @ RequestMapping__アノテーションの代替として機能します。受信リクエストをハンドラ関数にルーティングするために使用されます。
@FunctionalInterface
public interface RouterFunction<T extends ServerResponse> {
Mono<HandlerFunction<T>> route(ServerRequest request);
//...
}
通常は、__http://docs.spring.io/spring/docs/5.0.0.M5/javadoc-api/org/springframework/web/reactive/function/server/RouterFunctions.html#route-org.springframeworkをインポートできます。 .web.reactive.function.server.RequestPredicate-org.springframework.web.reactive.function.server.HandlerFunction-[RouterFunctions.route()]、完全なルーター関数を書くのではなく、ルートを作成するためのヘルパー関数。
それは__RequestPredicateを適用することでリクエストをルーティングすることを可能にします。
public static <T extends ServerResponse> RouterFunction<T> route(
RequestPredicate predicate,
HandlerFunction<T> handlerFunction)
RouterFunction
を返すことで、
route()
を連鎖させて入れ子にして、強力で複雑なルーティング方式を構築できます。
4.機能的Webを利用したリアクティブRESTアプリケーション
Spring WebFluxチュートリアルの手引き
で、注釈付きの
__ @ RestController
and
WebClientを使用して、小さな
__EmployeeManagement
RESTアプリケーションを作成します。
それでは、
Router
関数と
Handler
関数を使って同じアプリケーションを作成しましょう。
まず始めに、
私たちは
RouterFunction
を使用してルートを作成し、
Employeeのリアクティブストリームを公開および消費します。
ルートはSpringのBeanとして登録されており、Springの設定として使用される任意のクラス内に作成できます。
4.1. 単一リソース
単一の
Employee
リソースを公開する
__RouterFunction
__を使用して最初のルートを作成しましょう。
@Bean
RouterFunction<ServerResponse> getEmployeeByIdRoute() {
return route(GET("/employees/{id}"),
req -> ok().body(
employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class));
}
分解するために、最初の引数は
handler.
I.eを呼び出すHTTP GETリクエストを定義します。パスが
__/employee/\ {id}
で、要求がGET型の場合にのみ、
employeeRepositoryから一致する
Employee__を返します。
4.2. 収集リソース
次に、コレクションリソースを公開するために別のルートを追加しましょう。
@Bean
RouterFunction<ServerResponse> getAllEmployeesRoute() {
return route(GET("/employees"),
req -> ok().body(
employeeRepository().findAllEmployees(), Employee.class));
}
4.3. 単一リソースの更新
最後に、
__従業員
__リソースを更新するためのルートを追加しましょう。
@Bean
RouterFunction<ServerResponse> updateEmployeeRoute() {
return route(POST("/employees/update"),
req -> req.body(toMono(Employee.class))
.doOnNext(employeeRepository()::updateEmployee)
.then(ok().build()));
}
5.ルートを作成する
-
私達は単一のルーター機能で一緒にルートを構成することもできます。
上記で作成したルートを組み合わせてみましょう。
@Bean
RouterFunction<ServerResponse> composedRoutes() {
return
route(GET("/employees"),
req -> ok().body(
employeeRepository().findAllEmployees(), Employee.class))
.and(route(GET("/employees/{id}"),
req -> ok().body(
employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class)))
.and(route(POST("/employees/update"),
req -> req.body(toMono(Employee.class))
.doOnNext(employeeRepository()::updateEmployee)
.then(ok().build())));
}
ここでは、
__RouterFunction.and()
__を使用してルートを結合しました。
最後に、
__EmployeeManagement
アプリケーションに必要な
Router
と
__Handlerを使用して、すべてのREST APIを作成しました。私たちのアプリケーションを実行するためには、異なるルートを使用することも、上記で作成した単一のルートを使用することもできます。
6.ルートをテストする
-
ルートをテストするために
WebTestClient
を使うことができます。 **
__WebTestClientを使用してルートをテストするには、
we
bindToRouterFunction
__を使用してルートをバインドし、テストクライアントインスタンスを構築する必要があります。
getEmployeeByIdRoute
をテストしましょう。
@Test
public void givenEmployeeId__whenGetEmployeeById__thenCorrectEmployee() {
WebTestClient client = WebTestClient
.bindToRouterFunction(config.getEmployeeByIdRoute())
.build();
Employee expected = new Employee("1", "Employee 1");
given(employeeRepository.findEmployeeById("1")).willReturn(Mono.just(employee));
client.get()
.uri("/employees/1")
.exchange()
.expectStatus()
.isOk()
.expectBody(Employee.class)
.isEqualTo(expected);
}
同様に
getAllEmployeesRoute
:
@Test
public void whenGetAllEmployees__thenCorrectEmployees() {
WebTestClient client = WebTestClient
.bindToRouterFunction(config.getAllEmployeesRoute())
.build();
List<Employee> employeeList = new ArrayList<>();
Employee employee1 = new Employee("1", "Employee 1");
Employee employee2 = new Employee("2", "Employee 2");
employeeList.add(employee1);
employeeList.add(employee2);
Flux<Employee> employeeFlux = Flux.fromIterable(employeeList);
given(employeeRepository.findAllEmployees()).willReturn(employeeFlux);
client.get()
.uri("/employees")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Employee.class)
.isEqualTo(employeeList);
}
また、更新された
__Employee
instanceが
EmployeeRepository
を介して更新されていることをアサートすることで、
updateEmployeeRoute__をテストすることもできます。
@Test
public void whenUpdateEmployee__thenEmployeeUpdated() {
WebTestClient client = WebTestClient
.bindToRouterFunction(config.updateEmployeeRoute())
.build();
Employee employee = new Employee("1", "Employee 1 Updated");
client.post()
.uri("/employees/update")
.body(Mono.just(employee), Employee.class)
.exchange()
.expectStatus()
.isOk();
verify(employeeRepository).updateEmployee(employee);
}
WebTestClient
を使用したテストの詳細については、https://www.baeldung.com/spring-5-webclient[
WebClient
および
WebTestClient
を使用した作業]のチュートリアルを参照してください。
7. 概要
このチュートリアルでは、Spring 5で新しい機能的なWebフレームワークを紹介し、その2つのコア関数
__Router
と
Handler
__を調べ、要求を処理して応答を送信するためのさまざまな経路の作成方法を学びました。
また、https://www.baeldung.com/spring-webflux[Spring 5 WebFluxガイド]で紹介された
__EmployeeManagement
__applicationを新しいフレームワークで作り直しました。
その基礎を
Reactor
に置くと、リアクティブフレームワークはデータストアへのリアクティブアクセスに完全に光ります。残念ながら、
MongoDB
などのいくつかの
NoSQL
データベースを除いて、ほとんどのデータストアはまだそのようなリアクティブアクセスを提供していません。
いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-5-reactive-security[Githubでの使用]にあります。