Spring Boot 响应式 WebFlux 从入门到精通

响应式编程基础

响应式编程是一种基于数据流和变化传播的编程范式。Spring WebFlux 是 Spring 框架提供的响应式 Web 栈,基于 Reactor 库实现。核心概念包括 Publisher(发布者)、Subscriber(订阅者)和背压(Backpressure)机制。

Reactor 提供两种核心类型:Mono(0-1 个元素)和 Flux(0-N 个元素)。创建示例:

java 复制代码
Mono.just("Hello")
Flux.fromIterable(Arrays.asList(1, 2, 3))

项目初始化

使用 Spring Initializr 创建项目时需选择 Reactive Web 依赖。Maven 配置示例:

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

基础启动类需启用响应式支持:

java 复制代码
@SpringBootApplication
public class WebfluxApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebfluxApplication.class, args);
    }
}

路由与处理器

WebFlux 提供函数式路由声明方式。典型路由配置:

java 复制代码
@Bean
public RouterFunction<ServerResponse> routes() {
    return RouterFunctions.route()
        .GET("/hello", request -> 
            ServerResponse.ok().body(Mono.just("Hello WebFlux"), String.class))
        .build();
}

注解式控制器示例:

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {
    
    @GetMapping("/{id}")
    public Mono<User> getUser(@PathVariable String id) {
        return userRepository.findById(id);
    }
}

响应式数据库集成

Spring Data 提供响应式 Repository 支持。配置 MongoDB 示例:

yaml 复制代码
spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/test

响应式 Repository 接口:

java 复制代码
public interface UserRepository extends ReactiveMongoRepository<User, String> {
    Flux<User> findByAgeGreaterThan(int age);
}

错误处理机制

全局异常处理示例:

java 复制代码
@ExceptionHandler
public Mono<ResponseEntity<String>> handle(Exception ex) {
    return Mono.just(ResponseEntity
        .status(HttpStatus.INTERNAL_SERVER_ERROR)
        .body(ex.getMessage()));
}

响应式错误处理操作符:

java 复制代码
return userService.getUser(id)
    .onErrorResume(e -> Mono.just(new User("fallback")));

测试策略

WebTestClient 是测试 WebFlux 的主要工具:

java 复制代码
@SpringBootTest
class UserControllerTest {
    
    @Autowired
    private WebTestClient webClient;

    @Test
    void testGetUser() {
        webClient.get().uri("/users/1")
            .exchange()
            .expectStatus().isOk();
    }
}

高级特性

服务器推送事件(SSE)实现:

java 复制代码
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamEvents() {
    return Flux.interval(Duration.ofSeconds(1))
        .map(i -> "Event " + i);
}

响应式 WebSocket 支持:

java 复制代码
@Bean
public HandlerMapping webSocketHandlerMapping() {
    Map<String, WebSocketHandler> map = new HashMap<>();
    map.put("/echo", new EchoHandler());
    
    return new SimpleUrlHandlerMapping(map, -1);
}

性能优化

关键配置参数:

yaml 复制代码
server:
  reactor:
    netty:
      max-in-memory-size: 10MB
      connection-timeout: 30s

背压策略建议:

  • 使用 onBackpressureBuffer 缓冲溢出
  • 采用 limitRate 限制请求速率
  • 实现自定义 BaseSubscriber 控制消费速度
相关推荐
lpfasd12311 小时前
Spring Boot 定时任务详解(从入门到实战)
spring boot·后端·python
咩图11 小时前
Sketchup软件二次开发+Ruby+VisualStudioCode
java·前端·ruby
moxiaoran575311 小时前
Go语言的文件操作
开发语言·后端·golang
我命由我1234511 小时前
Android 开发问题:Duplicate class android.support.v4.app.INotificationSideChannel...
android·java·开发语言·java-ee·android studio·android-studio·android runtime
熬夜敲代码的小N11 小时前
Unity大场景卡顿“急救包”:从诊断到落地的全栈优化方案
java·unity·游戏引擎
坚持学习前端日记11 小时前
容器化中间件的优缺点
java·中间件
黑客老李11 小时前
一次有趣的通杀
java·数据库·mysql
季明洵11 小时前
反转字符串、反转字符串II、反转字符串中的单词
java·数据结构·算法·leetcode·字符串
赴前尘11 小时前
记一次golang进程执行卡住的问题排查
开发语言·后端·golang
虫小宝11 小时前
查券返利机器人的异步任务调度:Java XXL-Job+Redis实现海量查券请求的分布式任务分发
java·redis·分布式