You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 18:43:11