Spring Boot Clean架构下Mapper归属与映射责任划分咨询
关于Clean架构下Spring Boot CRUD应用的映射器与映射责任问题解答
一、映射器的归属层
根据Clean架构的依赖规则(核心层不依赖外层,外层依赖核心层),映射器的归属按以下方式划分:
dtoToPojo映射器:属于infrastructure层。DTO是对外交互的专属模型,Pojo是用例层的核心业务模型,基础设施层负责适配外部请求/响应到核心用例逻辑,因此该映射器放在infrastructure层,确保用例层完全感知不到DTO的存在。entityToPojo/pojoToEntity映射器:属于entity层(数据访问层)。Entity是持久化专属模型,用例层不应直接依赖持久化细节,由数据访问层负责将自身的Entity与用例层的Pojo互相转换,让用例层只关注业务逻辑,无需关心数据持久化的模型结构。
如果映射逻辑复杂,也可以单独抽出一个独立的mapping模块,但需保证该模块仅依赖被映射模型所在的层(如依赖infrastructure的DTO、useCases的Pojo、entity的Entity),且核心useCases层不依赖这个mapping模块,维持内层不依赖外层的规则。
二、映射责任的归属原则
核心遵循**「外层向核心层转换,依赖方负责转换」**的规则,确保核心用例层的独立性:
- 控制器(infrastructure层)调用用例服务(useCases层):由控制器(调用方)负责将
UserDto转换为UserPojo后传递给用例服务。这不属于破坏隔离——Clean架构允许外层依赖核心层的模型,而用例层完全不知道DTO的存在,符合核心层与外层的隔离要求。你担心的POJO信息共享是合理的,因为Pojo是核心业务模型,外层依赖核心模型是架构设计的既定规则,关键是核心层不能依赖外层模型。 - 用例服务(useCases层)调用Repository(entity层):由Repository所在的entity层负责将
UserPojo转换为UserEntity做持久化,或把查询到的UserEntity转换为UserPojo返回给用例服务。用例层仅处理Pojo,无需感知Entity的结构,保持核心逻辑的纯净。
代码示例参考
控制器层(infrastructure)新增用户实现
@RestController @RequestMapping("/users") public class RestUserController { private final UserUseCase userUseCase; private final UserDtoToPojoMapper dtoToPojoMapper; // 归属infrastructure层 public RestUserController(UserUseCase userUseCase, UserDtoToPojoMapper dtoToPojoMapper) { this.userUseCase = userUseCase; this.dtoToPojoMapper = dtoToPojoMapper; } @PostMapping public ResponseEntity<Void> addUser(@RequestBody UserDto userDto) { UserPojo userPojo = dtoToPojoMapper.map(userDto); userUseCase.addUser(userPojo); return ResponseEntity.status(HttpStatus.CREATED).build(); } }
Entity层Repository实现
@Repository public class UserRepositoryImpl implements UserRepository { private final JpaUserRepository jpaUserRepository; private final UserEntityToPojoMapper entityToPojoMapper; // 归属entity层 private final UserPojoToEntityMapper pojoToEntityMapper; // 归属entity层 public UserRepositoryImpl(JpaUserRepository jpaUserRepository, UserEntityToPojoMapper entityToPojoMapper, UserPojoToEntityMapper pojoToEntityMapper) { this.jpaUserRepository = jpaUserRepository; this.entityToPojoMapper = entityToPojoMapper; this.pojoToEntityMapper = pojoToEntityMapper; } @Override public UserPojo save(UserPojo userPojo) { UserEntity userEntity = pojoToEntityMapper.map(userPojo); UserEntity savedEntity = jpaUserRepository.save(userEntity); return entityToPojoMapper.map(savedEntity); } }
用例层服务实现
@Service public class UserUseCase { private final UserRepository userRepository; public UserUseCase(UserRepository userRepository) { this.userRepository = userRepository; } public void addUser(UserPojo userPojo) { // 仅处理业务逻辑,如校验 if (StringUtils.isBlank(userPojo.getUsername())) { throw new IllegalArgumentException("用户名不能为空"); } userRepository.save(userPojo); } }
内容的提问来源于stack exchange,提问作者user1379280
相关产品推荐
相关产品推荐

