MateCloud代码规范:DDD四层架构编码最佳实践
MateCloud代码规范DDD四层架构编码最佳实践【免费下载链接】matecloudMateCloud是一款基于Spring Cloud Alibaba的微服务架构。目前已经整合Spring Boot 4.0.7、 SpringCloud 2025、Spring Cloud Alibaba 2025、Spring Security Oauth2、Feign、Dubbo、JetCache、RocketMQ等支持多租户的低代码平台Saas平台开发套件项目地址: https://gitcode.com/GitHub_Trending/ma/matecloudMateCloud微服务脚手架基于Spring Cloud Alibaba构建采用领域驱动设计DDD架构模式为开发者提供了一套完整的微服务开发解决方案。本文将深入解析MateCloud的DDD四层架构编码规范帮助开发者快速掌握这一企业级微服务架构的核心设计理念和实践方法。 DDD四层架构概述MateCloud严格遵循DDD领域驱动设计原则将系统分为四个清晰的层次确保代码结构清晰、职责分离、易于维护。这种架构模式是现代微服务开发的黄金标准特别适合复杂业务系统的开发。四层架构核心设计每个业务模块都按照以下标准结构组织vip.mate.{service}/ ├── trigger/ # 入站适配器控制器层 ├── application/ # 应用服务层编排层 ├── domain/ # 领域层核心业务逻辑 ├── infrastructure/ # 基础设施层技术实现 └── types/ # 类型定义层错误码、常量等层间依赖规则trigger → application → domain ← infrastructure ↑ ↑ types types铁律领域层零框架依赖- 不允许Spring、MyBatis、Sa-Token等任何框架注解领域层不依赖基础设施层- 通过Repository/Port接口反转依赖应用层不直接操作DAO- 必须通过Repository接口触发层不包含业务逻辑- 仅做参数校验、权限检查、委托调用基础设施层不定义业务规则- 仅负责技术实现️ 领域层规范业务核心的纯净之地聚合根设计模式聚合根是DDD的核心概念它封装实体及其关联的值集合是事务一致性的边界。在MateCloud中聚合根的设计遵循以下原则// 聚合根包装实体 操作流 public class UserAggregate { private final User user; private final ListUserOperateStream operateStreams new ArrayList(); // 工厂方法创建聚合 public static UserAggregate create(String username, String mobile) { User user User.create(username, mobile); UserAggregate agg new UserAggregate(user); agg.addOperateStream(UserOperateType.CREATE, 创建用户); return agg; } // 业务方法——状态变更只能通过聚合方法 public void freeze() { user.checkActive(); user.setStatus(UserStatus.FROZEN); addOperateStream(UserOperateType.FREEZE, 冻结用户); } }关键要点外部不直接修改实体字段只通过聚合的业务方法聚合方法内记录操作流审计追踪工厂方法中完成初始化验证使用getAndClearOperateStreams()在持久化后清理事件领域实体设计领域实体是业务的核心对象它们承载着业务规则和状态// 实体使用工厂方法包含业务守卫 public class User extends BaseEntity { private String username; private String mobile; private UserStatus status; // 工厂方法生成ID 初始状态 public static User create(String username, String mobile) { User user new User(); user.setId(UUID.randomUUID().toString().replace(-, )); user.setStatus(UserStatus.ACTIVE); user.setUsername(username); user.setMobile(mobile); return user; } // 业务守卫方法 public void checkActive() { if (!UserStatus.ACTIVE.equals(this.status)) { throw UserException.of(UserErrorCode.USER_FROZEN); } } }实体设计规范实体继承BaseEntity自动获得id、createdAt、updatedAt、deleted、lockVersionID使用UUID去连字符在工厂方法中生成不使用任何框架注解TableField、Column等只出现在PO中状态变更通过语义化方法不暴露setter给外部直接调用仓储接口设计仓储接口定义在领域层实现放在基础设施层// 定义在 domain/adapter/repository/ public interface UserRepository { void save(UserAggregate aggregate); void update(UserAggregate aggregate); OptionalUserAggregate findById(String id); OptionalUserAggregate findByUsername(String username); boolean existsByUsername(String username); PageResultUser pageQuery(String keyword, int offset, int limit); }仓储规范仓储操作聚合根不操作裸实体查询方法返回Optional不返回null分页查询返回PageResultEntity不暴露底层SQL细节如LambdaQueryWrapper 应用层规范CQRS分离与业务编排CQRS命令查询分离MateCloud严格遵循CQRS模式将写操作和读操作完全分离写操作 → CommandServiceService RequiredArgsConstructor public class UserCommandService { private final IUserDomainService userDomainService; private final UserRepository userRepository; private final DomainEventPublisher eventPublisher; Transactional(rollbackFor Exception.class) public void createUser(CreateUserRequest req) { // 1. 通过领域服务创建聚合 UserAggregate agg userDomainService.createUser( req.getUsername(), req.getMobile(), req.getPassword()); // 2. 持久化 userRepository.save(agg); // 3. 发布领域事件 eventPublisher.publishAsync(new UserCreatedEvent(agg.getUser().getId())); } }读操作 → QueryService接口 实现// 接口 public interface IUserQueryService { PageResultUserResponse page(String keyword, int pageNum, int pageSize); UserResponse findById(String id); } // 实现 Service RequiredArgsConstructor public class UserQueryServiceImpl implements IUserQueryService { private final UserRepository userRepository; private final UserConvertor convertor; Override public PageResultUserResponse page(String keyword, int pageNum, int pageSize) { int offset (pageNum - 1) * pageSize; PageResultUser page userRepository.pageQuery(keyword, offset, pageSize); return PageResult.of(convertor.toResponseList(page.getList()), page.getTotal()); } }CQRS规范Command和Query绝不混在同一个类中CommandService标注Transactional(rollbackFor Exception.class)QueryService使用接口 impl分离便于mock和替换查询不走领域服务直接通过仓储读取MapStruct对象转换所有对象转换必须使用MapStruct禁止手动逐字段拷贝Mapper(componentModel spring) public interface UserConvertor { // 默认映射——忽略敏感字段 Mapping(target password, ignore true) UserResponse toResponse(User user); // 值对象映射 Named(statusToCode) default Integer statusToCode(UserStatus status) { return status null ? null : status.getCode(); } Named(codeToStatus) default UserStatus codeToStatus(Integer code) { return code null ? null : UserStatus.fromCode(code); } }转换器规范使用componentModel spring支持依赖注入敏感字段password默认ignore true值对象枚举↔code转换使用Named方法转换器定义在application/convertor/应用层和infrastructure/adapter/repository/convertor/基础设施层️ 基础设施层规范技术实现细节仓储实现仓储实现负责将领域对象持久化到数据库Repository RequiredArgsConstructor public class UserRepositoryImpl implements UserRepository { private final UserDao userDao; private final UserInfraConvertor convertor; Override Transactional(rollbackFor Exception.class) public void save(UserAggregate aggregate) { // 1. 转换并保存主实体 UserPO po convertor.toPO(aggregate.getUser()); userDao.insert(po); // 2. 保存操作流 ListUserOperateStream streams aggregate.getAndClearOperateStreams(); streams.forEach(s - streamDao.insert(convertor.toStreamPO(s))); } Override public OptionalUserAggregate findById(String id) { UserPO po userDao.selectById(id); if (po null) return Optional.empty(); User user convertor.toEntity(po); return Optional.of(new UserAggregate(user)); } }仓储实现规范仓储实现标注Repository聚合保存时同时持久化操作流/关联实体PO↔Entity转换通过MapStruct完成findById返回Optional不返回null多对多关系如admin_role使用先删后插策略持久化对象PO设计Data TableName(mate_user) public class UserPO extends BasePO { TableId(type IdType.ASSIGN_ID) private String id; private String username; private String mobile; private String password; private Integer status; TableLogic private Integer deleted; Version private Integer lockVersion; TableField(fill FieldFill.INSERT) private LocalDateTime createdAt; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updatedAt; }PO设计规范PO类名以PO结尾放在infrastructure/dao/po/包下表名使用mate_前缀ID使用IdType.ASSIGN_ID雪花算法必须包含deleted逻辑删除、lockVersion乐观锁、createdAt、updatedAtJSON类型字段使用JacksonTypeHandler审计日志表LoginLog、OperationLog不使用逻辑删除 触发层规范API接口设计REST控制器设计RestController RequestMapping(/api/v1/users) RequiredArgsConstructor SaCheckLogin public class UserController { private final UserCommandService commandService; private final IUserQueryService queryService; // 创建 PostMapping SaCheckPermission(Perms.USER_ADD) public ResultVoid create(RequestBody Valid CreateUserRequest req) { commandService.createUser(req); return Result.ok(); } // 分页查询 GetMapping SaCheckPermission(Perms.USER_LIST) public ResultPageResultUserResponse page( RequestParam(required false) String keyword, Valid BasePageReq pageReq) { return Result.ok(queryService.page(keyword, pageReq.getPageNum(), pageReq.getPageSize())); } // 详情 GetMapping(/{id}) SaCheckPermission(Perms.USER_LIST) public ResultUserResponse getById(PathVariable String id) { return Result.ok(queryService.findById(id)); } }API设计规范类级别标注SaCheckLogin方法级别标注SaCheckPermissionAPI路径统一前缀/api/v1/返回值统一包装为ResultT分页使用BasePageReq默认pageNum1, pageSize10, 最大500控制器不包含业务逻辑仅做参数校验和委托写操作用POST/PUT/DELETE读操作用GETRPC服务实现DubboService(version RpcConstants.VERSION, group RpcConstants.GROUP_SYSTEM, timeout RpcConstants.DEFAULT_TIMEOUT) public class RpcUserServiceImpl implements IRpcUserService { private final IUserQueryService queryService; Override public ResultUserInfoResponse getUserByUsername(String username) { UserResponse user queryService.findByUsernameForAuth(username); return user ! null ? Result.ok(toRpcResponse(user)) : Result.fail(用户不存在); } }RPC规范使用DubboService注解指定version、group、timeout返回值统一用ResultT包装超时时间使用RpcConstants常量RPC实现类放在trigger/rpc/包下 类型层规范错误码与异常处理错误码设计MateCloud采用统一的错误码编码规则{MODULE}{TYPE}{SEQ}Getter AllArgsConstructor public enum UserErrorCode implements ErrorCode { PARAM_NULL (USRA001, 请求参数为空), DUPLICATE_MOBILE (USRB001, 手机号已存在), USER_NOT_FOUND (USRB002, 用户不存在), USER_FROZEN (USRB003, 用户已冻结), OLD_PASSWORD_WRONG(USRB004, 原密码错误), PASSWORD_TOO_SHORT(USRA002, 密码不能少于6位); private final String code; private final String message; }错误码编码规则段值说明MODULESYS/USR/ORD/SEC/TEN/NTC/ADM模块缩写3字母TYPEA参数校验错误TYPEB业务逻辑错误TYPECRPC调用错误TYPED数据库错误TYPEE外部服务错误SEQ001-999序号模块异常设计public class UserException extends BizException { private UserException(ErrorCode errorCode) { super(errorCode.getCode(), errorCode.getMessage()); } public static UserException of(ErrorCode errorCode) { return new UserException(errorCode); } }异常处理规范每个模块一个自定义Exception类继承BizException使用静态工厂of(ErrorCode)创建实例不暴露公共构造函数业务异常用BizException.of(ErrorCode)抛出不在Controller中try-catch业务异常交由全局处理 最佳实践总结1. 领域层保持纯净核心原则领域层是业务逻辑的核心必须保持零框架依赖。这意味着不使用Spring、MyBatis、Sa-Token等任何框架注解不直接依赖数据库、缓存、消息队列等基础设施通过Repository和Port接口与外部世界交互业务规则在领域实体和聚合根中实现2. CQRS严格分离命令查询分离写操作和读操作完全分离带来以下好处写操作Command负责业务逻辑和状态变更读操作Query负责数据查询和展示两者使用不同的数据模型避免读写冲突查询可以针对性能优化使用专门的查询模型3. 统一的对象转换MapStruct统一转换所有对象转换必须使用MapStruct应用层转换器application/convertor/基础设施层转换器infrastructure/adapter/repository/convertor/敏感字段默认忽略如password值对象转换使用Named方法4. 统一的API设计RESTful API规范POST /api/v1/{resource} # 创建 GET /api/v1/{resource} # 分页列表 GET /api/v1/{resource}/{id} # 详情 PUT /api/v1/{resource}/{id} # 更新 DELETE /api/v1/{resource}/{id} # 删除逻辑删除 PUT /api/v1/{resource}/{id}/freeze # 状态变更 POST /api/v1/{resource}/batch-{act} # 批量操作5. 错误处理标准化全局异常处理由mate-web-starter提供统一的异常处理异常类型HTTP状态码处理方式BizException200返回Result.fail(code, msg)MethodArgumentNotValidException200提取首个校验失败消息BindException200提取首个校验失败消息Exception(兜底)500记录日志返回通用错误 开发工具与CLIMateCloud提供了强大的CLI工具帮助开发者快速创建和维护DDD四层架构创建新模块# 使用CLI创建新模块 java -jar mate-cli/target/mate-cli.jar new module mate-order --port 9060代码生成# 根据数据库表生成DDD四层代码 java -jar mate-cli/target/mate-cli.jar gen code --table mate_order --module mate-order --service mate-system数据库迁移# 执行数据库迁移 java -jar mate-cli/target/mate-cli.jar db migrate --module mate-system 学习资源官方文档docs/conventions/coding-standards.md - 详细的编码规范DDD示例mate-biz/mate-system/ - 完整的DDD四层架构示例RFC文档docs/rfcs/008-mate-system-ddd.md - DDD架构设计文档配置策略docs/conventions/config-strategy.md - 五层配置体系 快速开始要开始使用MateCloud的DDD四层架构请遵循以下步骤环境准备确保Java 21、Maven、Docker已安装基础设施启动运行make infra-up启动MySQL、Redis、Nacos等创建新模块使用CLI工具创建业务模块遵循规范按照本文的DDD四层架构规范编写代码运行测试执行mvn test验证代码正确性 结语MateCloud的DDD四层架构编码规范为微服务开发提供了一套完整、清晰、可维护的解决方案。通过严格的分层设计、清晰的职责分离和统一的编码规范开发者可以快速构建高质量的企业级微服务应用。无论你是DDD新手还是经验丰富的架构师遵循这些最佳实践都能帮助你构建出更加健壮、可维护的系统。记住领域层零框架依赖是铁律这是保持业务逻辑纯净性的关键开始你的MateCloud DDD之旅吧享受清晰架构带来的开发乐趣✨【免费下载链接】matecloudMateCloud是一款基于Spring Cloud Alibaba的微服务架构。目前已经整合Spring Boot 4.0.7、 SpringCloud 2025、Spring Cloud Alibaba 2025、Spring Security Oauth2、Feign、Dubbo、JetCache、RocketMQ等支持多租户的低代码平台Saas平台开发套件项目地址: https://gitcode.com/GitHub_Trending/ma/matecloud创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考