Spring Webflux – Kotlin DSL –实现的演练

先前的博客文章中,我描述了Spring Web Framework中的响应式编程支持Spring Webflux如何使用基于Kotlin的DSL使用户能够以非常直观的方式描述路由。 在这里,我想探索一些底层实现。

描述一组端点的样本DSL看起来像这样:

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)
        }
    }

}

为了分析样本,让我从一个较小的工作示例开始:

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
    }
}

路由定义的核心是“路由器”功能:

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

通过以下方式定义:

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

参数“ routes”是lambda表达式的一种特殊类型, 称为带接收器的Lambda表达式 。 这意味着在路由器功能的上下文中,此lambda表达式只能由“ RouterFunctionDsl”实例调用,这是在函数主体中使用apply方法完成的操作,这也意味着在lambda表达式主体中“此”是“ RouterFunctionDsl”的实例。 知道这一点后,便可以访问“ RouterFunctionDsl”的方法,该方法之一就是示例中使用的GET,GET的定义如下:

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

还有其他表达相同端点的方法:

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

在Kotlin中非常巧妙地实现为:

fun GET(pattern: String): RequestPredicate = RequestPredicates.GET(pattern)

operator fun RequestPredicate.invoke(f: (ServerRequest) -> Mono<ServerResponse>) {
 ...
}

此处,使用模式的GET返回一个“ RequestPredicate”,已为其定义了一个扩展函数 (在DSL的上下文中),称为invoke,而后者又是一个特别命名的运算符

或第三种方式:

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

这是通过在String类型上添加扩展功能来实现的,并通过以下方式定义:

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

我觉得Spring Webflux很好地利用了Kotlin DSL,使其中一些路由定义易于阅读,同时保持简洁。

这应该提供足够的入门知识,以探索Spring WebfluxRouting DSL的源代码。

我的示例可在此处的github存储库中找到 – https://github.com/bijukunjummen/webflux-route-with-kotlin

翻译自: https://www.javacodegeeks.com/2017/09/spring-webflux-kotlin-dsl-walkthrough-implementation.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值