github: https://github.com/zhanzhanqi/web-flux
本文将web-flux demo中的handler模式的使用方式进行了节选,直接将本文中代码服务复制到ide中就可以执行。至于深层次的reactive的套路及其好处,有了更深的体会后在开文章记录。
pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
目前spring支持reactive的repository只有mongo, redis, Cassandra 暂时不支持基于jdbc的MySQL,因此选用了mongo作为repository。在本地使用docker的方式安装mongo可以参考Docker安装Mongo
Model
@Document
class User {
@Id
var id: Long? = null
var firstName: String = ""
var lastName: String = ""
var age: Int = -1
}
Reactive Repository
interface ReactiveUserRepository : ReactiveMongoRepository<User, Long>
链接Mongo 配置
spring.data.mongodb.host=localhost
spring.data.mongodb.database=admin
spring.data.mongodb.port=27017
spring.data.mongodb.username=mongoadmin
spring.data.mongodb.password=secret
FunctionHandler
@Component
class UserHandler(private val userRepository: ReactiveUserRepository) {
fun listUser(request: ServerRequest): Mono<ServerResponse> {
val users = userRepository.findAll()
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(users, User::class.java)
}
fun createUser(request: ServerRequest): Mono<ServerResponse> {
val user = request.body(BodyExtractors.toMono(User::class.java))
.flatMap { userRepository.save(it) }
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(user, User::class.java)
}
fun getUser(request: ServerRequest): Mono<ServerResponse> {
val userId = request.pathVariable("id").toLong()
val notFound = ServerResponse.notFound().build()
val userMono = userRepository.findById(userId)
return userMono
.flatMap {
user -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(user))
}.switchIfEmpty(notFound)
}
}
Router
@Configuration
class UserRouter(private val handler: UserHandler) {
@Bean
fun myRouter() = router {
accept(MediaType.APPLICATION_JSON).nest {
GET("router/user/{id}", handler::getUser)
POST("router/user", handler::createUser)
GET("router/user",handler::listUser)
}
}
}
启动容器
@SpringBootApplication
class WebFluxApplication
fun main(args: Array<String>) {
runApplication<WebFluxApplication>(*args)
}
启动
访问