利用Ktor+KMongo打造全栈异步非阻塞后端架构

阅读 102

2022-02-27


简要介绍

2017年Spring推出了WebFlux,填补了Java世界没有异步非阻塞架构的尴尬(nodejs正式靠着这个起家的),同时联合响应式数据库(MongoDB、Redis、Apache Cassandra、CouchDB)可以打造后端全栈异步非阻塞架构,其中采用​​Reactor​​作为异步执行基础.但是把玩了一段时候后,发现响应式的程序真是让人废啊.如果没有接触的可以看看《响应式编程(Reactive Programming)介绍》. 前一段时间在开发安卓应用时,厌倦了RxJava(类似Reactor)之流的基于数据流的异步操作,忽然发现Kotlin里有协程,这个东东用起来就很顺手了,不用特别把业务处理变成数据流了.

再往后深入研究,发现Kotlin的后端开发有类似于springboot的Ktor,还有连接mongo数据库的响应式框架Kmongo,这就完美了,哈哈.

简要代码(详见Demo源代码)

fun Route.userRoutes() {

val logger: Logger = LoggerFactory.getLogger("UserController")
val client: CoroutineClient by inject()

val dbName = "demo"
val collectionName = "users"

route("/users") {

get("/list") {
val users = client.getDatabase(dbName)
.getCollection<User>(collectionName)
.find()
.toList()
call.respond(HttpStatusCode.OK, users)
}

post<CreateUserRequest>("/add") {request ->
val user = User(userName = request.userName,
password = request.password,
email = request.email)
client.getDatabase(dbName)
.getCollection<User>(collectionName)
.insertOne(user)
call.respond(HttpStatusCode.OK)
}
}
}

Demo源代码

https://github.com/cxyzy1/ktor-kmongo-sample

Demo使用说明


  1. 本地要启动mongo数据库,如果端口不是默认的27017,则需要修改Application.kt中​​"mongodb://127.0.0.1:27017"​​的端口
  2. 使用的数据库是demo,集合是users,如果和本地mongo数据库不一致,请修改UserController.kt中定义.
  3. 插入数据
    采用PostMan等工具发送POST请求
    a) 请求地址: http://localhost:8080/users/add b) 数据样例:

{
"userName" : "jerry",
"password" : "123456",
"email" : "test2@gmail.com"
}

c) 请求头类型为json

利用Ktor+KMongo打造全栈异步非阻塞后端架构_数据库

利用Ktor+KMongo打造全栈异步非阻塞后端架构_json_02

4. 查询数据(类型为GET)

请求地址: ​​​​http://localhost:8080/users/list​​​​

利用Ktor+KMongo打造全栈异步非阻塞后端架构_数据_03

5. 对于插入数据和查询数据,也可以直接通过代码中的ApplicationTest的testAddData和testList完成.

class ApplicationTest {

@Test
fun testAddData() {
withTestApplication({ module(testing = true) }) {
handleRequest(HttpMethod.Post, "/users/add")
{
addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
setBody(
mapOf(
"userName" to "jerry5",
"password" to "123456",
"email" to "test@gmail.com"
).json
)
}.apply {
assertEquals(HttpStatusCode.OK, response.status())
}
}
}

@Test
fun testList() {
withTestApplication({ module(testing = true) }) {
handleRequest(HttpMethod.Get, "/users/list").apply {
assertEquals(HttpStatusCode.OK, response.status())
System.out.println(response.content)
}
}
}
}

​​点击关注专栏,查看最新技术分享​​

更多技术总结好文,请关注:「程序园中猿」


精彩评论(0)

0 0 举报