系统架构与分支规范

📅 2026/8/27 20:17:25
系统架构与分支规范
--- trigger: always_on --- # 后端架构与分支规范 ## 分层架构 - 严格遵守 Controller → Service → Store → Mapper 的分层原则 - Controller层负责API映射参数接收不处理业务逻辑 - Service层核心业务逻辑参数校验 - Store层数据储存层负责数据查询和事务处理DSTransactional - Mapper层数据库操作 ## 扩展分层 - **Agg聚合根/Model层**领域模型对象位于 sales 模块的 model 包下 - 使用 Getter ToString不用 Data通过方法封装属性设置 - 必须提供 create() / modify() / fillingDbId() 方法封装属性设置 - create 和 modify 共用私有 fillingMainData() 方法 - 全参构造函数用于 Entity→Agg 的转换 - **Bond层**复杂业务编排层承载核心业务逻辑几千行级别命名如 XxxBond - 标注 Component直接注入多个 Mapper/Service/Store - 不遵循标准 CRUD 模板按业务场景定制方法 - **Trans层**跨领域业务编排层命名如 XxxServiceTrans - 标注 Component使用 DSTransactional 保障多数据源事务 - 整合多个 Service/Store 的调用 ## 各层注解规范 | 层 | 类注解 | 注入方式 | 事务注解 | |---|--------|---------|--------| | Controller | RestController Slf4j Api(tags...) | Autowired | 无 | | Service接口 | 无 | - | - | | ServiceImpl | Slf4j Service | Autowired | 无事务放Store层 | | Store接口 | 无 | - | - | | StoreImpl | Slf4j Component | Autowired | DSTransactional写操作 | | Agg | Getter ToString ApiModel | - | - | | Bond | Component | Autowired | 按需 | **关键规则** - Store层用 Component 而非 Service - 事务使用 DSTransactionalcom.baomidou.dynamic.datasource.annotation.DSTransactional而非 Transactional - 特殊场景使用 DS(primary) 或 DS(hologres) 指定数据源 ## 各层包路径归属 | 类型 | 包路径 | 所属模块 | |------|--------|----------| | Entity | com.lvcc.biz.entity.sales.{module} | biz | | DTO | com.lvcc.biz.dto.sales.{module} | biz | | QueryDTO | com.lvcc.biz.dto.sales.{module} | biz | | VO | com.lvcc.biz.vo.sales.{module} | biz | | Mapper | com.lvcc.biz.dao.sales.{module} | biz | | Mapper XML | biz/src/main/resources/mapper/{module}/ | biz | | Controller | com.lvcc.sales.{module}.controller | sales | | Service | com.lvcc.sales.{module}.service | sales | | ServiceImpl | com.lvcc.sales.{module}.service.impl | sales | | Agg(Model) | com.lvcc.sales.{module}.model | sales | | Store | com.lvcc.sales.{module}.store 或 com.lvcc.biz.store.sales.{module} | sales/biz | | StoreImpl | com.lvcc.sales.{module}.store.impl 或 com.lvcc.biz.store.sales.{module}.impl | sales/biz | | Bond | com.lvcc.sales.{module}.bond | sales | ## 各层返回值规范 | 层 | 操作类型 | 返回类型 | 示例 | |----|---------|---------|------| | Controller | 所有 | RestResponse | RestResponse.success().setData(data) | | Service | 分页查询 | PageVO | PageAiOutboundCallVO | | Service | 新增/删除/更新 | boolean | throws FebsException | | Service | 详情查询 | VO | throws FebsException | | Store | 分页查询 | ListVO | Mapper直返 | | Store | 新增或修改 | Long主键ID | - | | Store | 删除 | boolean | - | | Store | 详情 | Agg 或 VO | - | ## Controller 标准方法模板 java // 新增POST /save PostMapping(/save) public RestResponse create(RequestBody XxxDTO dto) throws FebsException // 单删GET /delete/{id} GetMapping(/delete/{id}) public RestResponse delete(PathVariable(id) String id) throws FebsException // 批删POST /delete/batch PostMapping(/delete/batch) public RestResponse deleteBatch(RequestBody String ids) throws FebsException // JSON字符串手动解析 // 分页查询POST /list PostMapping(/list) public RestResponse queryXxxPage(RequestBody XxxQueryDTO queryDto) // 不throws // 详情查询GET /get/{id} GetMapping(/get/{id}) public RestResponse findXxxById(PathVariable(id) String id) throws FebsException // 更新POST /update/{id} PostMapping(/update/{id}) public RestResponse update(PathVariable(id) String id, RequestBody XxxDTO dto) throws FebsException **关键规则** - id 参数类型统一为 **String**Controller层在Service层转为Long - 批量操作接收 JSON字符串用 JSON.parse() 手动解析 - 更新操作路径为 /update/{id}将 id 设置到 dtodto.setId(Long.valueOf(id)) - 分页查询方法 **不throws FebsException** - 返回格式RestResponse.success().setData(data) 或 RestResponse.success(成功) ## 分页查询模式 - QueryDTO 继承 PageBaseDTO含 pageNum1, pageSize10 - Service层构造 PageVO 对象new Page(pageNum, pageSize) - Store层方法签名ListVO queryXxxPage(PageVO queryPage, XxxQueryDTO queryDto) - Mapper方法签名ListVO queryXxxRecord(PageVO queryPage, Param(data) XxxQueryDTO queryDto) - MyBatis-Plus 自动将分页信息填充到 Page 对象 ## DDD设计原则 - 领域模型优先数据库仅为持久化细节 - 通过聚合根(Agg)维护数据一致性 - 通过限界上下文将系统拆分为高内聚、低耦合的模块 - Agg不使用 Setter / Data 注解通过 create/modify/fillingDbId 方法保证不可变性 - 添加字段需同步改动Entity → StoreImpl → ServiceImpl → Agg → VO/DTO按需 ## Store层保存模式 java DSTransactional public Long saveXxxRecord(XxxAgg saveEntity, String userKey) { XxxEntity curEntity this.findXxxEntityByDataKey(saveEntity.getId()); // 1. 查询现有实体 curEntity this.buildXxxEntity(curEntity, saveEntity, userKey); // 2. 构建实体 if (ObjectUtil.isEmpty(curEntity.getId())) { xxxMapper.insert(curEntity); // 3. id为空 → insert } else { xxxMapper.updateById(curEntity); // 4. id有值 → updateById } saveEntity.fillingDbId(curEntity.getId()); // 5. 回填聚合根的id return curEntity.getId(); // 6. 返回主键 } - buildXxxEntity 方法处理新增/修改场景的Entity构建 - 逻辑删除set(XxxEntity::getDeleted, 1) 而非物理删除 - 查询实体时必须加 eq(XxxEntity::getDeleted, 0) 条件 ## 获取当前用户 - Service层UserInfo user JWTUtil.getCurrentUser(); String userKey String.valueOf(user.getUserId()); - Controller层日志FebsUtil.getCurrentUser() ## 数据权限注解 java ComplexPermissions(andPermissionEnums MenuPermEnum.XXX, message 暂无访问权限) - 用于Controller方法上控制菜单权限 - 权限码在 MenuPermEnum 枚举中定义 ## 操作日志注解 java Log(操作描述) - 用于Controller方法上记录操作日志 ## 代码生成器 - 新增表必须采用代码生成器生成的代码风格 - 添加字段时需改动位置Entity → StoreImpl → ServiceImpl → Agg层 → VO和DTO按需补充 ## 代码分支规范 - 主分支master_test禁止在未经允许的情况下直接修改并提交代码 - 需求合集factory_platform合集名称如 factory_platform_M20250901 - 线上优化master_online_optimization日期如 master_online_optimization_20251101 - 普通需求factory_需求英文命名日期如 factory_ai_perms_20250929 - 合并规范完成需求后进行代码提测测试完成后由组长根据上线清单进行代码合并 - 提测时必须在提测单标明是否有SQL并将SQL粘贴到提测单 - 测试开始时需重新合并 master_production 到自己的提测分支 ## 本地开发环境 - 本地开发禁止连接测试环境的消息队列 - 微服务版本禁止注册测试环境的注册中心 - 启动顺序Nacos → Gateway → Sales → 其他按需启动 - 外网映射在dev环境 t_service_config 表中配置地址格式 http://factorytransmit.frp.lbbtech.com/服务标识/接口路径