1. Tổng quan

Có vẻ như Netty là người bạn khá thân thiết với Spring, và lần này là với NettyWebServer. Cũng dễ hiểu tại sao Spring lại sử dụng Netty với chỉ có NettyWebServer là mới cung cấp giao diện lập trình với Reactive, còn lại các server như tomcat hay jetty thì chưa. Vậy nên để tiết kiệm chi phí cài đặt thì việc một thứ đã có sẵn sẽ đơn giản hơn rất nhiều.

2. Cài đặt

Để có thể sử dụng spring webflux, chúng ta cần thêm các dependencies vào project, ví dụ với gradle:

implementation 'org.springframework.boot:spring-boot-starter:' + springBootVersion
implementation 'org.springframework.boot:spring-boot-starter-webflux:' + springBootVersion

Với springBootVersion=2.7.0

3. Ví dụ

Giả sử chúng ta đang cần làm 1 service để quản lý tác giả sách, và chúng ta cần cung cấp 1 số API chẳng hạn, thì thay vì trả về ResponseEntity hay Data thì chúng ta sẽ trả về Mono hoặc Flux:

package com.tvd12.example.spring_webflux_jpa.controller;

import com.tvd12.example.spring_webflux_jpa.entity.Author;
import com.tvd12.example.spring_webflux_jpa.repository.AuthorRepository;
import com.tvd12.example.spring_webflux_jpa.request.AddAuthorRequest;
import com.tvd12.example.spring_webflux_jpa.response.AddAuthorResponse;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

@RestController
@RequestMapping("/api/v1")
@AllArgsConstructor
public class AuthorController {

    private final AuthorRepository authorRepository;

    @PostMapping("/author/add")
    public Mono<AddAuthorResponse> authorsAddPost(
        @RequestBody AddAuthorRequest request
    ) {
        Author author = new Author();
        author.setName(request.getName());
        author.setCreatedTime(LocalDateTime.now());
        author.setUpdatedTime(LocalDateTime.now());
        Author saved = authorRepository.save(author);
        return Mono.just(new AddAuthorResponse(saved.getId()));
    }

    @GetMapping("/author/{authorId}")
    public Mono<ResponseEntity<Author>> authorsAuthorIdGet(
        @PathVariable("authorId") long authorId
    ) {
        return authorRepository.findById(authorId)
            .map(it ->
                Mono.just(
                    ResponseEntity.ok(it)
                )
            ).orElseGet(() ->
                Mono.just(
                    ResponseEntity.notFound()
                        .build()
                )
            );
    }
}

Việc lập trình theo cách thức mới này cũng sẽ dài dòng hơn và khó debug hơn lập trình thông thường một chút, nhưng đổi lại nó sẽ có khả năng phục vụ được nhiều request đồng thời hơn. Ví dụ đầy đủ bạn có thể tham khảo tại Github Repo.