凭借Kotlin的幽雅,还有Spring Boot 2.0的简洁,可以通过简单几行代码实现大流量数据接口,同时具备背压处理能力,下面用一个简单的示例介绍接口实现步骤:
注意选择生成项目的构建工具,可以根据自己的编译习惯选择 Maven 或者 Gradle ,编程语言选择 Kotlin ,Spring Boot版本选择 2.0.4 或者以上版本,根据项目信息填写group和artifact标题。
然后重点来了,需要选择哪些依赖包?因为我们要用Spring5框架的响应式编程模式提供REST接口,第一个依赖包需要 Reactive Web ,另外我们需要用MongoDB保存接口数据,也是通过响应式访问MongoDB,还需要一个 Reactive MongoDB 依赖包。
最后点击生成工程(Generate Project),解压下载后的工程压缩包。
可以使用STS或者IntelliJ IDEA,由于IntelliJ IDEA强大的辅助完成功能,个人强烈推荐后者。
在src目录内可以找到主入口函数的类文件cn/springspace/kotlinapp/KotlinAppApplication.kt,
在该文件内我们首先需要添加数据实体bean的类定义
@Document data class Book(val name: String, val author: String, val publish: Date)
然后添加MongoDB的访问接口,该接口继承自ReactiveMongoRepository,已默认实现了数据搜索,保存,删除等基本方法,也可以根据自己的需要添加实现一些自定义方法,本例中仅使用到保存和列表的方法就无需自定义方法了。
interface BookRepository : ReactiveMongoRepository<Book, String>
fun main(args: Array<String>) { runApplication<KotlinAppApplication>(*args) { addInitializers( beans { bean { val bookRepository = ref<BookRepository>() bookRepository.deleteAll() .thenMany( Flux.fromStream( Stream.generate { "Spring 空间【${UUID.randomUUID()}】" } .limit(30))) .map { Book(it, "Michael Chen", Date()) } .flatMap { bookRepository.save(it) } .thenMany(bookRepository.findAll()) .subscribe { println(it) } } } ) } }
以上的数据初始化的操作分解如下:
步骤1: bookRepository.deleteAll() , 删除系统内历史数据;
步骤2: Flux.fromStream( Stream.generate { "Spring 空间【${UUID.randomUUID()}】" } .limit(30)) , 生成一个数组长度为30的字符串序列,每个元素的格式为:"Spring 空间【${UUID.randomUUID()}】";
步骤3: map { Book(it, "Michael Chen", Date()) } ,以上一步的字符为源头生成30个Book实体类;
步骤4: flatMap { bookRepository.save(it) } ,保存这30个Book到MongoDB;
步骤5: thenMany(bookRepository.findAll()) ,检索系统内最新的Book数据;
步骤6: subscribe { println(it) } ,打印输出检索出来的数据。
注意:以上步骤中最后一步 subscribe() 最为关键,该步骤是控制启动步骤1到步骤6的总开关,没有该步骤,前面几步的动作都不会执行。
凭借Kotlin优雅的DSL语言,我们可以更简洁的表达方式实现多个功能块的定义,如下部分是在beans内部添加WEB响应模块的bean:
bean { val bookRepository = ref<BookRepository>() val interval = Flux.interval(Duration.ofMillis(100)) router { GET("/books") { ServerResponse.ok() .contentType(MediaType.TEXT_EVENT_STREAM) .body(Flux.zip(interval, bookRepository.findAll()).map { it.t2 }) } } }
其中contentType(MediaType.TEXT_EVENT_STREAM)部分控制服务端输出的数据格式为SSE方式的文本事件流,如果要简单的一次性输出所有数据,该部分的bean定义如下:
bean { val bookRepository = ref<BookRepository>() router { GET("/books") { ServerResponse.ok().body(bookRepository.findAll()) } } }
打开浏览器,访问 http://localhost:8080/books 接口,可以得到以下数据:
data:{"name":"Spring 空间【b1b1faa9-2b74-48a5-aa99-52458d5e55cc】","author":"Michael Chen","publish":"2018-09-06T07:31:41.245+0000"} data:{"name":"Spring 空间【bda0a990-ae11-4286-88f9-977ced8199d4】","author":"Michael Chen","publish":"2018-09-06T07:31:41.453+0000"} data:{"name":"Spring 空间【3c7494b4-474d-4c89-a786-8f611dcae225】","author":"Michael Chen","publish":"2018-09-06T07:31:41.454+0000"} data:{"name":"Spring 空间【e05b8f31-bf37-4bb3-9e74-002b9a1bd008】","author":"Michael Chen","publish":"2018-09-06T07:31:41.459+0000"} data:{"name":"Spring 空间【a3882221-a001-4b72-b478-d04db6f498f6】","author":"Michael Chen","publish":"2018-09-06T07:31:41.495+0000"} data:{"name":"Spring 空间【30c18fa6-d326-4ce0-9ed4-0cbbc1a20025】","author":"Michael Chen","publish":"2018-09-06T07:31:41.467+0000"} ...................
以上工程的示例代码下载地址: https://gitee.com/chenbichao/kotlin-app