KotlinによるSpring Webflux

1.概要

このチュートリアルでは、Kotlinプログラミング言語を使用してSpring WebFluxモジュールを使用する方法を説明します。

エンドポイントを定義する際に、アノテーションベースおよびラムダベースのスタイルアプローチを使用する方法を説明します。

2. Spring WebFluxとKotlin

Spring 5のリリースでは、2つの新しい大きな機能が導入されました。その中には、リアクティブプログラミングパラダイムのネイティブサポートとKotlinプログラミング言語を使用する可能性があります。

このチュートリアルを通して、私たちはすでに環境を設定し(この問題についてはhttps://www.baeldung.com/spring-boot-kotlin[このチュートリアルの1つ]を参照して)、Kotlin言語の構文(https:/)を理解していると仮定します。トピックに関する/www.baeldung.com/kotlin[その他のチュートリアル]。

3.アノテーションベースのアプローチ

WebFluxでは、 @ RequestMapping @ PathVariable などのSpringMVCフレームワークアノテーション、または @ RestController @ GetMapping などの便利なアノテーションを使用して、着信要求を処理するエンドポイントを既知の方法で定義できます。

  • アノテーション名が同じであるという事実にもかかわらず、 WebFluxの はメソッドを 非ブロック にします。**

たとえば、このエンドポイントは次のとおりです。

@GetMapping(path =["/numbers"],
  produces =[MediaType.APPLICATION__STREAM__JSON__VALUE])
@ResponseBody
fun getNumbers() = Flux.range(1, 100)

いくつかの最初の整数のストリームを生成します。サーバーが localhost:8080 で実行されている場合は、次のコマンドでサーバーに接続します。

curl localhost:8080/stream

要求された番号を印刷します。

4.ラムダベースのアプローチ

エンドポイントを定義するためのより新しいアプローチは、バージョン1.8以降にJavaに存在するラムダ式によるものです。 Kotlinの助けを借りて、ラムダ式は以前のバージョンのJavaでも使用することができます。

WebFluxでは、ルーターの機能は RequestPredicate (つまり、誰がリクエストを管理すべきか)と HandlerFunction (つまり、リクエストの作り方)によって決定される機能です。

  • ハンドラ関数は ServerRequest インスタンスを受け取り、 Mono <ServerResponse> を生成します。

Kotlinでは、 最後の関数引数がラムダ式である場合、それは括弧 の外側に置くことができます。

そのような構文によって、要求述語とハンドラ関数の間の分割を強調することができます。

router {
    GET("/route") { __ -> ServerResponse.ok().body(fromObject(arrayOf(1, 2, 3))) }
}

ルーター機能用

この関数は、判読可能な形式になっています。GET型の要求が/routeに到着すると、HTTPステータスOKで、本文から構築された本文で応答を構築します(要求の内容を無視します。与えられたオブジェクト

さて、WebFluxでそれを機能させるためには、ルーター関数をクラスに入れるべきです:

@Configuration
class SimpleRoute {

    @Bean
    fun route() = router {
        GET("/route") { __ -> ServerResponse.ok().body(fromObject(arrayOf(1, 2, 3))) }
    }
}

多くの場合、私たちのアプリケーションのロジックは、より洗練されたルーター機能を構築する必要があります。

WebFluxでは、Kotlinのルーター関数DSLは accept and or nest invoke GET POST などのさまざまな関数を extension functions によって定義しています。

router {
    accept(TEXT__HTML).nest {
        (GET("/device/") or GET("/devices/")).invoke(handler::getAllDevices)
    }
}

handler 変数は、標準の HandlerFunction シグネチャを持つメソッド getAllDevices() を実装するクラスのインスタンスである必要があります。

fun getAllDevices(request: ServerRequest): Mono<ServerResponse>

私達が上で述べたように。

関心事の適切な分離を維持するために、関連しないルータ機能の定義を別々のクラスに入れることができます。

@Configuration
class HomeSensorsRouters(private val handler: HomeSensorsHandler) {
    @Bean
    fun roomsRouter() = router {
        (accept(TEXT__HTML) and "/room").nest {
            GET("/light", handler::getLightReading)
            POST("/light", handler::setLight)
        }
    }
   //eventual other router function definitions
}

String 値のメソッド pathVariable() を使ってパス変数にアクセスできます。

val id = request.pathVariable("id")

一方、 ServerRequest の本体へのアクセスは、 bodyToMono および bodyToFlux メソッドによって実現されます。

val device: Mono<Device> = request
  .bodyToMono(Device::class.java)

5.テスト

ルーターの機能をテストするために、テストしたいルーター SimpleRoute()。route() WebTestClient インスタンスを作成する必要があります。

…… var client = WebTestClient.bindToRouterFunction(SimpleRoute()。route())。build() ……

これで、ルータのハンドラ関数がステータスOKを返すかどうかをテストする準備が整いました。

client.get()
  .uri("/route")
  .exchange()
  .expectStatus()
  .isOk
  • WebTestClientインターフェースは、サーバを実行しなくても GET POST PUT などのすべてのHTTPリクエストメソッドをテストできるようにするメソッドを定義します。 **

レスポンスボディの内容をテストするために、 json() メソッドを使用することができます。

client.get()
  .uri("/route")
  .exchange()
  .expectBody()
  .json("[1, 2, 3]")

6.まとめ

この記事では、Kotlinを使用してWebFluxフレームワークの基本機能を使用する方法を説明しました。

エンドポイントを定義する際のよく知られたアノテーションベースのアプローチについて簡単に述べ、ラムダベースのスタイルアプローチでルーター機能を使用してそれらを定義する方法を説明するために時間をかけました。

すべてのコードスニペットは私達のリポジトリhttps://github.com/eugenp/tutorials/tree/master/spring-reactive-kotlin[GitHubに載っています]にあります。