# webflux-web **Repository Path**: kpret/webflux-web ## Basic Information - **Project Name**: webflux-web - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-01 - **Last Updated**: 2026-04-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring WebFlux 示例工程 这是一个适合教学和二次扩展的 Java WebFlux 示例项目。工程体量不大,但包含了一个清晰的 WebFlux 项目该有的核心部件:启动类、配置、控制器、服务、仓库、DTO、异常处理、SSE 流式接口、集成测试和结构化说明文档。 ## 功能概览 - `GET /api/health` 返回应用状态、应用名和技术栈信息,用来说明最简单的 `Mono` 返回方式。 - `GET /api/greetings/hello?name=Will` 返回欢迎语和时间戳,展示配置注入和轻量业务处理。 - `GET /api/products` 返回商品列表,展示 `Flux` 列表接口。 - `GET /api/products/{id}` 返回单个商品,不存在时走统一异常处理。 - `GET /api/products/category/{category}` 按分类过滤商品,展示路径参数与服务层校验。 - `POST /api/products` 创建商品,展示请求体接收、参数校验和 `Mono` 写入流程。 - `GET /api/products/stream` 返回 `text/event-stream`,展示 WebFlux 的流式响应能力。 - `GET /api/fn/**` 与上面同一批业务的函数式路由版本,展示 `RouterFunction + HandlerFunction` 写法。 ## 技术栈 - Java 21 - Spring Boot 3.5.6 - Spring WebFlux - Reactor - JUnit 5 - WebTestClient - Maven Wrapper ## 项目结构 ```text src ├── main │ ├── java/com/example/webfluxweb │ │ ├── WebfluxWebApplication.java │ │ ├── controller │ │ │ ├── GreetingController.java │ │ │ ├── HealthController.java │ │ │ └── ProductController.java │ │ ├── dto │ │ │ ├── CreateProductRequest.java │ │ │ ├── ErrorResponse.java │ │ │ ├── GreetingResponse.java │ │ │ ├── HealthResponse.java │ │ │ └── ProductResponse.java │ │ ├── exception │ │ │ ├── ApiExceptionHandler.java │ │ │ └── ProductNotFoundException.java │ │ ├── handler │ │ │ └── FunctionalApiHandler.java │ │ ├── model │ │ │ └── Product.java │ │ ├── repository │ │ │ └── InMemoryProductRepository.java │ │ ├── router │ │ │ └── FunctionalRoutesConfig.java │ │ └── service │ │ ├── GreetingService.java │ │ ├── HealthService.java │ │ └── ProductService.java │ └── resources │ └── application.properties ├── test │ └── java/com/example/webfluxweb │ └── WebfluxWebApplicationTests.java └── docs └── architecture.md ``` ## 层级关系 - Controller 层 只处理 HTTP 协议语义,负责收参、调用 service、返回 `Mono` 或 `Flux`。 - Service 层 放业务规则和流程编排,决定何时返回单值、何时返回流,以及异常如何抛出。 - Repository 层 负责数据存取。示例里使用内存仓库,重点突出 WebFlux 调用方式,而不是数据库配置。 - DTO / Model 层 DTO 面向接口输入输出,Model 面向领域实体,避免接口对象和存储对象混用。 - Exception 层 用 `@RestControllerAdvice` 做统一错误出口,保持接口返回格式一致。 ## 两种 WebFlux 写法 这个项目现在同时包含两套接口组织方式: - 注解式 路径在 `controller` 中定义,适合大多数 Spring 团队的常规开发方式。 - 函数式 路径集中定义在 `router`,处理逻辑放在 `handler`,更适合强调路由编排、过滤链和 WebFlux 的函数式风格。 对应关系如下: - 注解式商品列表:`GET /api/products` - 函数式商品列表:`GET /api/fn/products` - 注解式健康检查:`GET /api/health` - 函数式健康检查:`GET /api/fn/health` ## 一次请求是怎么流转的 以 `POST /api/products` 为例: 1. `ProductController#createProduct` 接收 JSON 请求体。 2. Controller 把请求交给 `ProductService#createProduct`。 3. Service 做参数校验,并调用 `InMemoryProductRepository#save`。 4. Repository 返回 `Mono`。 5. Service 把领域对象映射成 `ProductResponse`。 6. Controller 直接把 `Mono` 交给 WebFlux。 7. WebFlux 在订阅时执行整条链路,把结果编码成 HTTP 响应。 与传统 MVC 的区别在于,这里没有在控制器里“拿到值再返回”,而是一直传递 `Mono` / `Flux` 这一条响应式管道。 如果看函数式版本,则调用关系会变成: 1. `FunctionalRoutesConfig` 负责把 URL 映射到 handler。 2. `FunctionalApiHandler` 负责从 `ServerRequest` 取参数和请求体。 3. handler 调用已有的 `service`。 4. `service` 再调用 `repository`。 5. handler 最终组装 `ServerResponse` 返回。 ## 如何运行 ```bash ./mvnw spring-boot:run ``` ## 如何验证 ```bash ./mvnw test ``` ## 调用示例 ```bash curl http://localhost:8080/api/health curl "http://localhost:8080/api/greetings/hello?name=WebFlux" curl http://localhost:8080/api/products curl http://localhost:8080/api/products/1 curl http://localhost:8080/api/products/category/hardware curl -X POST http://localhost:8080/api/products \ -H "Content-Type: application/json" \ -d '{"name":"Reactive Mouse","category":"hardware","price":199.00}' curl -N http://localhost:8080/api/products/stream curl http://localhost:8080/api/fn/health curl "http://localhost:8080/api/fn/greetings/hello?name=Router" curl "http://localhost:8080/api/fn/products?category=hardware" curl -X POST http://localhost:8080/api/fn/products \ -H "Content-Type: application/json" \ -d '{"name":"Functional Mouse","category":"hardware","price":188.00}' curl -N http://localhost:8080/api/fn/products/stream ``` ## 为什么这个示例适合入门 - 代码足够小,容易一次看完。 - 结构完整,能看出真实项目的分层方式。 - 同时覆盖 `Mono`、`Flux`、异常处理、SSE 和测试。 - 文档和代码一一对应,便于拿来做团队内部教学样例。 ## 延伸阅读 - 结构与调用关系说明见 [docs/architecture.md](docs/architecture.md)