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