Spring Webflux非阻塞实现:多User实体转含部门列表的UserDTO
解决Spring Webflux下合并同一用户多数据的非阻塞实现
核心思路
利用响应式流的分组操作,先按用户ID聚合同一用户的所有数据,再将聚合后的部门信息整理为列表,最终组装成单个UserDTO,全程保持非阻塞特性。
步骤实现
1. 补全DepartmentDTO定义
首先需要定义对应部门信息的DTO类:
public class DepartmentDTO { private String department; private String departmentArea; // 构造器、Getter/Setter public DepartmentDTO(String department, String departmentArea) { this.department = department; this.departmentArea = departmentArea; } // 省略Getter/Setter方法 }
2. 修改服务层响应式流处理逻辑
将原有的直接映射逻辑替换为分组-聚合-转换的流程:
userRepo.findAllUsersByIds() // 按用户ID分组,同一ID的User进入同一响应式分组 .groupBy(User::getId) // 处理每个分组,转换为单个UserDTO .flatMap(groupedUsers -> groupedUsers // 将分组内的Flux<User>收集为Mono<List<User>>(非阻塞操作) .collectList() .map(users -> { // 提取用户基础信息(同一ID的name需保证一致) User baseUser = users.get(0); // 转换所有部门信息为DepartmentDTO列表,可按需去重 List<DepartmentDTO> deptList = users.stream() .map(user -> new DepartmentDTO(user.getDepartment(), user.getDepartmentArea())) .distinct() // 去除重复的部门记录 .collect(Collectors.toList()); // 组装最终的UserDTO UserDTO userDTO = new UserDTO(); userDTO.setId(baseUser.getId()); userDTO.setName(baseUser.getName()); userDTO.setDepartmentDTO(deptList); return userDTO; }) );
3. (可选)抽离映射逻辑到Mapper类
如果需要复用映射逻辑,可以将聚合转换的代码抽离到Mapper类中:
// Mapper类中的方法 public UserDTO mapToUserDTO(List<User> users) { if (users == null || users.isEmpty()) { return null; } User baseUser = users.get(0); List<DepartmentDTO> deptList = users.stream() .map(this::mapToDepartmentDTO) .distinct() .collect(Collectors.toList()); UserDTO dto = new UserDTO(); dto.setId(baseUser.getId()); dto.setName(baseUser.getName()); dto.setDepartmentDTO(deptList); return dto; } private DepartmentDTO mapToDepartmentDTO(User user) { return new DepartmentDTO(user.getDepartment(), user.getDepartmentArea()); }
此时服务层代码可简化为:
userRepo.findAllUsersByIds() .groupBy(User::getId) .flatMap(group -> group.collectList().map(mapper::mapToUserDTO));
关键注意事项
- 确保同一用户ID对应的
name字段数据一致,非规范化表可能存在数据冗余或不一致,需提前校验或处理。 distinct()可根据业务需求选择是否保留:如果数据库中同一用户同一部门有多条重复记录,使用该方法去重;若需保留所有历史记录则移除。- 所有操作均为响应式非阻塞操作,符合Spring Webflux的异步编程模型,不会阻塞线程。
内容的提问来源于stack exchange,提问作者Upen
相关产品推荐
相关产品推荐

