Spring WebFlux 响应式编程入门
Lisa Tan | 2026-08-27T20:55:03 | Java, Spring Boot
从 Reactor 核心概念出发,讲解 WebFlux 的 Mono/Flux 编程模型、WebClient 使用和与传统 MVC 的对比。
# Spring WebFlux 响应式编程入门 ## 什么是响应式编程? 响应式编程是一种面向异步数据流的编程范式。WebFlux 基于 Project Reactor,使用非阻塞 I/O,单线程即可处理大量并发连接。 ## 核心类型:Mono 和 Flux ```java // Mono: 0 或 1 个元素 Mono user = Mono.just(new User("张三")); Mono empty = Mono.empty(); // Flux: 0 到 N 个元素 Flux numbers = Flux.range(1, 10); Flux names = Flux.just("Alice", "Bob", "Charlie"); ``` ## 创建 WebFlux 应用 ```java @RestController @RequestMapping("/api/users") public class UserController { private final UserRepository repository; public UserController(UserRepository repository) { this.repository = repository; } @GetMapping public Flux listUsers() { return repository.findAll(); } @GetMapping("/{id}") public Mono> getUser(@PathVariable String id) { return repository.findById(id) .map(user -> ResponseEntity.ok(user)) .defaultIfEmpty(ResponseEntity.notFound().build()); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public Mono createUser(@RequestBody User user) { return repository.save(user); } @PutMapping("/{id}") public Mono updateUser(@PathVariable String id, @RequestBody User update) { return repository.findById(id) .flatMap(existing -> { existing.setName(update.getName()); existing.setEmail(update.getEmail()); return repository.save(existing); }); } } ``` ## 操作符详解 ```java // map: 同步转换 Flux upperNames = names.map(String::toUpperCase); // flatMap: 异步转换(可能乱序) Flux orders = userIds.flatMap(id -> orderService.findByUserId(id)); // concatMap: 异步转换(保持顺序) Flux orderedResults = userIds.concatMap(id -> orderService.findByUserId(id)); // filter + take Flux activeUsers = users .filter(u -> u.getStatus().equals("active")) .take(10); // zip: 合并多个流 Mono>> combined = Mono.zip( userService.findById(id), orderService.findByUserId(id).collectList() ); // 错误处理 Mono safe = userService.findById(id) .onErrorResume(NotFoundException.class, e -> Mono.empty()) .onErrorReturn(new User("default")); ``` ## WebClient 替代 RestTemplate ```java WebClient client = WebClient.builder() .baseUrl("https://api.example.com") .defaultHeader("Authorization", "Bearer " + token) .build(); Mono user = client.get() .uri("/users/{id}", userId) .retrieve() .bodyToMono(UserDTO.class); // 发送 POST 请求 Mono order = client.post() .uri("/orders") .bodyValue(orderRequest) .retrieve() .bodyToMono(OrderDTO.class); ``` ## MVC vs WebFlux | 维度 | Spring MVC | Spring WebFlux | |------|-----------|----------------| | 线程模型 | 一请求一线程 | 事件循环 | | 适用场景 | CRUD 业务 | I/O 密集型 | | 阻塞调用 | 允许 | 禁止 | | 学习曲线 | 低 | 中 | | JDBC 支持 | 原生 | 需 R2DBC | ## 总结 WebFlux 适合网关、代理、聚合等 I/O 密集型场景。传统 CRUD 业务用 MVC 更简单。不建议在已有 MVC 项目中强行迁移。