Kotlin 协程 + Spring webflux 开发后端
前言
后端响应式是未来,吞吐量会更大,而资源占用更少,其用到了类似Android系统的Loop(事件循环)机制,而协程可以减少线程等待的消耗,并且同步式的编程方式使代码可读性更高,两个仿佛天生就是一对,所以就来简单的了解并配置一下Kotlin 协程 + Spring webflux的后端项目
正文
项目配置采用Gradle(毕竟我是做Android开发的,所以一切亲Android体系),数据库用的Mysql
首先settings.gradle.kts文件,项目名暂定JavaKj
rootProject.name = "JavaKj"
然后build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.3.5.RELEASE"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm") version "1.4.10"
kotlin("plugin.spring") version "1.4.10"
}
group = "com.lt.javakj"
version = "0.0.1"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencies {
//测试库
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
}
testImplementation("junit:junit:4.13")
testImplementation("io.projectreactor:reactor-test")
//spring webflux 响应式服务端框架,使用方法基本等同spring mvc(除了返回值)
implementation("org.springframework.boot:spring-boot-starter-webflux")
//webflux 返回值的协程支持
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
//webflux await的协程支持
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive")
//异步数据库支持
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
//mysql 的异步数据库支持
implementation("dev.miku:r2dbc-mysql")
//json解析(默认就是jackson)
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
//webflux kt扩展
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
//kt反射
implementation("org.jetbrains.kotlin:kotlin-reflect")
//kotlin核心库
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
//网络请求
implementation("com.squareup.okhttp3:okhttp:3.14.9")
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
目前项目结构是这样:
然后打开application.properties文件增加以下配置
#修改端口号
server.port=xxxxx (最好大于一万并小于65535,具体自行搜索)
#
#配置mysql r2dbc
spring.r2dbc.password=mysql密码
spring.r2dbc.username=mysql用户名
spring.r2dbc.url=r2dbcs:mysql://mysqlip:mysql端口/mysql的数据库名
然后spring webflux的操作其他还是跟spring mvc是一样的,这里就不赘述,唯一不同的是返回值
示例controller
import kotlinx.coroutines.reactor.mono
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.r2dbc.core.DatabaseClient
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import javax.annotation.Resource
/**
* creator: lt 2020/11/11 lt.dygzs@qq.com
* effect : test的接口
* warning:
*/
@RestController
@RequestMapping("/api/ad")
class TestInterface {
@GetMapping("/findAll")
fun findAll(): Flux<TestBean?> //返回Flux<T>表示是个list
@GetMapping("/addData")
fun addData(): Mono<TestBean> //返回Mono<T>表示是单个对象
}
示例数据库表的实体类和数据库操作对象
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
import org.springframework.data.repository.kotlin.CoroutineSortingRepository
/**
* creator: lt 2020/11/11 lt.dygzs@qq.com
* effect : 表实体类
* warning:
*/
@Table("feedback")
class TestBean(
@Id
var id: Long? = null,//如果id为null,则为自增,并且需要var
val create_time: Long = 0,
val content: String? = null,
val user_id: Long = 0,
val urls: String? = null,
val is_solve: Int = 0,
val solve_time: Long = 0,
)
/**
* creator: lt 2020/11/11 lt.dygzs@qq.com
* effect : 数据库操作类
* warning:
*/
interface TestDB : CoroutineSortingRepository<TestBean, Long>
然后就可以在接口里去增删改查数据了,比如增加一条数据
其中mono{}是开启了一个以Mono<T>为返回值的协程,而TestDB实现了CoroutineSortingRepository接口,所以其内的大部分方法都是suspend的
这里我们插入一条数据(挂起了),然后打印一下返回值(就是插入的对象),并返回这个对象
这个db提供了如savexxx,findxxx,deletexxxx等简单的操作,如果需要自己执行sql语句,需要如下:
需要注意的是,如果flux内的suspend lambda走完的话,这个接口就完成了,也就是说如果是在回调中在调用channel.send是无效的,需要改成使用协程的形式
自己执行sql语句还有以下的api:
//查询,返回Flux<T>
databaseClient.execute("select * from client_user").as(ClientUser.class)
.fetch()
.all();
//插入,返回Mono<Integer>
databaseClient.insert().into(ClientUser.class)
.using(clientUser)
.fetch().rowsUpdated();
然后使用基本就ok了,可以直接运行测试一下
扩展
可能第一次自己写sql没有绑定到数据库表上,如下图,然后我就大概说一下怎么绑定,绑定完就会有sql的代码提示了
步骤如下:
然后如下简单配置一下
会弹出
在里面执行一下,然后在同步一下
use 你的数据库名 ;
然后回去
可以把默认的(所有文件)改成这个库,并把当前文件的私有设置删掉(或者你单独改某文件也行)
然后sql语句就有代码提示了
如果有什么写的不对的请大佬们指出,我用的还不熟练,相当于给自己写了一个文档 \嘿嘿
end
本文地址:https://blog.csdn.net/qq_33505109/article/details/109644018