Статьи

Spring Webflux — Kotlin DSL — пошаговое руководство по внедрению

В предыдущем сообщении в блоге я описал, как Spring Webflux, поддержка реактивного программирования в Spring Web Framework, использует DSL на основе Kotlin, чтобы пользователи могли описывать маршруты очень интуитивно понятным способом. Здесь я хотел бы немного изучить базовую реализацию.

Пример DSL, описывающий набор конечных точек, выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package sample.routes
 
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType.APPLICATION_JSON
import org.springframework.web.reactive.function.server.router
import sample.handler.MessageHandler
 
@Configuration
class AppRoutes(private val messageHandler: MessageHandler) {
 
    @Bean
    fun apis() = router {
        (accept(APPLICATION_JSON) and "/messages").nest {
            GET("/", messageHandler::getMessages)
            POST("/", messageHandler::addMessage)
            GET("/{id}", messageHandler::getMessage)
            PUT("/{id}", messageHandler::updateMessage)
            DELETE("/{id}", messageHandler::deleteMessage)
        }
    }
 
}

Чтобы проанализировать образец, позвольте мне начать с небольшого рабочего примера:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
import org.junit.Test
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.reactive.function.server.ServerResponse.ok
import org.springframework.web.reactive.function.server.router
 
class AppRoutesTest {
 
    @Test
    fun testSimpleGet() {
        val routerFunction = router {
            GET("/isokay", { _ -> ok().build() })
        }
 
        val client = WebTestClient.bindToRouterFunction(routerFunction).build()
 
        client.get()
                .uri("/isokay")
                .exchange()
                .expectStatus().isOk
    }
}

Сердцем определения маршрута является функция «маршрутизатор»:

1
2
3
4
5
import org.springframework.web.reactive.function.server.router
...
val routerFunction = router {
    GET("/isokay", { _ -> ok().build() })
}

который определяется следующим образом:

1
fun router(routes: RouterFunctionDsl.() -> Unit) = RouterFunctionDsl().apply(routes).router()

Параметр «маршруты» представляет собой специальный тип лямбда-выражения, называемый лямбда-выражением с получателем . Это означает, что в контексте функции маршрутизатора это лямбда-выражение может быть вызвано только экземплярами «RouterFunctionDsl», что и делается в теле функции с использованием метода apply , это также означает в теле лямбда-выражения « this »относится к экземпляру« RouterFunctionDsl ». Знание этого открывает доступ к методам RouterFunctionDsl, одним из которых является GET, который используется в примере, GET определяется следующим образом:

1
2
3
fun GET(pattern: String, f: (ServerRequest) -> Mono<ServerResponse>) {
  ...
}

Есть другие способы выразить ту же конечную точку:

1
GET("/isokay2")({ _ -> ok().build() })

реализовано в Kotlin очень умно, как:

1
2
3
4
5
fun GET(pattern: String): RequestPredicate = RequestPredicates.GET(pattern)
 
operator fun RequestPredicate.invoke(f: (ServerRequest) -> Mono<ServerResponse>) {
 ...
}

Здесь GET с шаблоном возвращает «RequestPredicate», для которого была определена функция расширения (в контексте DSL), называемая invoke, которая, в свою очередь, является оператором со специальным именем .

Или третий способ:

1
"/isokay" { _ -> ok().build() }

который реализуется путем добавления функции расширения для типа String и определяется следующим образом:

1
2
3
operator fun String.invoke(f: (ServerRequest) -> Mono<ServerResponse>) {
  ...
}

Мне кажется, что Spring Webflux превосходно использует Kotlin DSL для упрощения чтения некоторых из этих определений маршрутов, оставаясь при этом лаконичным.

Это должно обеспечить достаточно учебника для изучения исходного кода Routing DSL в Spring Webflux .

Мои образцы доступны в репозитории github здесь — https://github.com/bijukunjummen/webflux-route-with-kotlin

Ссылка: Spring Webflux — Kotlin DSL — пошаговое руководство по внедрению от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry.