Spring Boot中starter-web与starter-webflux依赖的适用场景及CRUD实现疑问
Spring Boot Web vs WebFlux:区别、场景与CRUD实现
先处理你当前的依赖问题
同时引入spring-boot-starter-web和spring-boot-starter-webflux会触发Spring Boot自动配置冲突——web依赖基于Servlet栈(默认用Tomcat),webflux基于Reactive栈(默认用Netty),同时引入时Spring Boot会优先启用Servlet栈,webflux的响应式特性无法正常生效。直接删除其中一个依赖,根据业务场景二选一即可。
核心区别对比
| 维度 | spring-boot-starter-web | spring-boot-starter-webflux |
|---|---|---|
| 编程模型 | 阻塞式(Servlet),同步IO | 非阻塞式(Reactive Streams),异步IO |
| 线程模型 | 每个请求分配独立线程,线程阻塞等待IO完成 | 少量工作线程处理所有请求,非阻塞IO不占用线程 |
| 适用负载类型 | CPU密集型、低/普通并发场景 | IO密集型、高并发场景(如API网关、实时数据服务) |
| 底层容器 | 默认Tomcat,可切换Jetty、Undertow | 默认Netty,可切换Tomcat/Jetty(需额外配置) |
| 依赖栈 | Spring MVC + Servlet API | Spring WebFlux + Reactive Streams API |
何时选择哪个?
选spring-boot-starter-web的场景
- 团队熟悉传统Spring MVC、Servlet编程范式,无需学习响应式编程
- 业务以CPU密集型任务为主(如复杂计算、批量数据处理)
- 现有系统基于Servlet栈,需要兼容或扩展
- 低到中等并发量的常规Web应用(如后台管理系统、普通业务API)
选spring-boot-starter-webflux的场景
- 高并发IO密集型场景(如实时消息推送、高流量API网关、大数据查询接口)
- 需要通过非阻塞IO降低线程开销,提升资源利用率
- 要整合响应式生态组件(如MongoDB Reactive、Redis Reactive)
- 开发实时交互应用(如聊天系统、实时数据仪表盘)
基于spring-boot-starter-web实现CRUD
1. 依赖配置(仅保留此依赖)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2. 实体类
public class User { private Long id; private String name; private Integer age; // 构造器、getter、setter省略 }
3. 同步阻塞式Controller
@RestController @RequestMapping("/users") public class UserController { private final Map<Long, User> userMap = new ConcurrentHashMap<>(); private AtomicLong idGenerator = new AtomicLong(1); // 查询所有用户 @GetMapping public List<User> listUsers() { return new ArrayList<>(userMap.values()); } // 根据ID查询单个用户 @GetMapping("/{id}") public User getUserById(@PathVariable Long id) { return userMap.get(id); } // 创建用户 @PostMapping public User createUser(@RequestBody User user) { Long userId = idGenerator.getAndIncrement(); user.setId(userId); userMap.put(userId, user); return user; } // 更新用户信息 @PutMapping("/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { User existingUser = userMap.get(id); if (existingUser != null) { existingUser.setName(user.getName()); existingUser.setAge(user.getAge()); userMap.put(id, existingUser); } return existingUser; } // 删除用户 @DeleteMapping("/{id}") public void deleteUser(@PathVariable Long id) { userMap.remove(id); } }
基于spring-boot-starter-webflux实现CRUD
1. 依赖配置(仅保留此依赖)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
2. 实体类(与上面一致)
public class User { private Long id; private String name; private Integer age; // 构造器、getter、setter省略 }
3. 非阻塞响应式Controller
@RestController @RequestMapping("/users") public class UserReactiveController { private final Map<Long, User> userMap = new ConcurrentHashMap<>(); private AtomicLong idGenerator = new AtomicLong(1); // 查询所有用户,返回Flux(多元素响应式流) @GetMapping public Flux<User> listUsers() { return Flux.fromIterable(userMap.values()); } // 根据ID查询单个用户,返回Mono(单元素响应式流) @GetMapping("/{id}") public Mono<User> getUserById(@PathVariable Long id) { return Mono.justOrEmpty(userMap.get(id)); } // 创建用户 @PostMapping public Mono<User> createUser(@RequestBody User user) { Long userId = idGenerator.getAndIncrement(); user.setId(userId); userMap.put(userId, user); return Mono.just(user); } // 更新用户信息 @PutMapping("/{id}") public Mono<User> updateUser(@PathVariable Long id, @RequestBody User user) { return Mono.justOrEmpty(userMap.get(id)) .map(existingUser -> { existingUser.setName(user.getName()); existingUser.setAge(user.getAge()); userMap.put(id, existingUser); return existingUser; }); } // 删除用户,返回Mono<Void>表示无返回值 @DeleteMapping("/{id}") public Mono<Void> deleteUser(@PathVariable Long id) { userMap.remove(id); return Mono.empty(); } }
内容的提问来源于stack exchange,提问作者Shefat-Hasnain
相关产品推荐
相关产品推荐

