리액터는 리액티브 스트림의 Publisher 인터페이스를 구현하는 모노(Mono)와 플럭스(Flux)라는 두가지 핵심 타입을 제공한다.
import reactor.core.publisher.Mono
fun main() {
val mono: Mono<String> = Mono.just("Hello")
mono.subscribe(::println) //결과 Hello
//println(mono) 결과 MonoJust
}

스프링 WebFlux는 클라이언트의 요청을 라우팅 하고 처리할 수 있는 람다(Lambda) 기반 프로그래밍 모델인 함수형 엔드포인트를 제공한다.
요청을 분석해 핸들러롤 라우팅하는 라우터 함수와 요청 객체를 전달받아 응답을 제공하는 핸들러 함수로 이루어져 있다.
@Configuration
class Router {
@Bean
fun helloRouter(handler: HelloHandler) : RouterFunction<ServerResponse> =
route()
.GET("/", handler::sayHello)
.build()
@Bean
fun userRouter(handler: UserHandler) : RouterFunction<ServerResponse> =
router {
"/users".nest {
GET("/{id}", handler::getUser)
GET("", handler::getAll)
}
}
}
@Component
class HelloHandler {
fun sayHello(req: ServerRequest) : Mono<ServerResponse> {
return ServerResponse.ok().bodyValue("Hello WebFlux")
}
}
data class User(val id: Long, val email: String)
@Component
class UserHandler {
val users = listOf(
User(id = 1, email = "user1@gmail.com")
User(id = 2, email = "user2@gmail.com")
)
fun getUser(req: ServerRequest) : Mono<ServerResponse> =
user.find { req.pathVariable("id").toLong() == it.id }
?.let {
ServerResponse.ok().bodyValue(it)
} ?: ServerResponse.notFound().build()
fun getAll(req: ServerRequest) : Mono<ServerResponse> =
ServerResponse.ok().bodyValue(users)
}
WebFlux에서도 Spring MVC와 동일하게 @RestController, @GetMapping과 같은 애노테이션을 사용하여 컨트롤러를 작성한다.
@RestController
class BookController(
private val bookService: BookService,) {
@PostMapping("/books")
fun add(@Requestbody request: Map<String, Any>) : Mono<Book> {
return bookService.add(request)
}
@GetMapping("/books")
fun getAll() : Flux<Book> {
return bookService.getAll()
}
@GetMapping("/books/{id}")
fun get(@PathVariable id: Int) : Mono<Book> {
return bookService.get(id)
}
@DeleteMapping("/books/{id}")
fun delete(@PathVariable id: Int) : Mono<Void> {
return bookService.delete(id)
}
}