Skip to main content

java-architecture-guide

Use when writing, reviewing, or refactoring Java business code in Spring Boot + MyBatis-Plus layered projects, especially for layering, transactions, exceptions, and naming conventions. Covers Controller, Facade, Service, and Mapper boundaries plus coding standards.

معلومات المصدر

المستودع
jianyun8023/my-skills
آخر نشاط في المصدر
١٨ يوليو ٢٠٢٦ في ١٢:٠٢
لغة SKILL.md المكتشفة
الصينية
النجوم
١
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
java-architecture-guide
description
Use when writing, reviewing, or refactoring Java business code in Spring Boot + MyBatis-Plus layered projects, especially for layering, transactions, exceptions, and naming conventions. Covers Controller, Facade, Service, and Mapper boundaries plus coding standards.
# Java 业务项目架构指南 适用于 Spring Boot + MyBatis-Plus 分层业务项目,重点约束分层职责、事务边界和错误处理方式。 ## 适用场景 - 新写业务模块、接口或服务实现时 - 代码评审中需要判断分层是否合理 - 重构 Service / Facade / Controller 边界时 - 团队成员需要快速对齐项目编码约束时 ## 不适用 - 纯算法类、脚本类、一次性工具代码 - 非分层架构项目(如纯事件驱动、Hexagonal、CQRS 独立架构) - 仅修改配置、SQL 或前端页面样式的任务 ## 快速工作流 1. 先确认当前需求落在哪一层,不要一开始就跨层写代码 2. 写操作先确认事务边界,跨服务编排放在 Facade 3. 查询逻辑优先在 Service 中用类型安全方式构建 4. 返回给 API 的数据统一走 DTO,不直接暴露 Entity ## 分层架构 四层单向调用,禁止反向或跨层依赖: ``` Controller → Facade → Service → Repository (Mapper) ``` ### 各层职责 | 层 | 职责 | 注入 | 禁止 | |---|---|---|---| | **Controller** | HTTP 入口、参数校验、响应封装 | Facade | 注入 Service;包含业务逻辑;添加事务 | | **Facade** | 跨服务编排、事务边界、DTO 组装 | 多个 Service、Converter | 直接操作 Mapper | | **Service** | 单一领域业务逻辑、数据操作 | 本域 Mapper、Converter | 注入其他 Service 或其他域的 Mapper | | **Repository** | 数据访问(继承 BaseMapper) | — | 添加自定义方法(查询在 Service 中构建) | ### 为什么引入 Facade 层 - **单一职责**: Service 层专注自己领域,不承担编排逻辑 - **降低耦合**: Service 不依赖其他 Service,可独立测试 - **事务清晰**: 跨服务事务统一在 Facade 管理 - **便于定位**: 业务编排集中在 Facade,排查问题路径清晰 ## 层间调用铁律 ### 规则 1: Controller 只注入 Facade ```java // CORRECT @RestController @RequiredArgsConstructor public class PolicyController { private final PolicyFacade facade; // ✅ @PostMapping public ApiResponse<IdResp> create(@Valid @RequestBody PolicyCreateReq req) { return ApiResponse.ok(new IdResp(facade.create(req))); } } // WRONG public class PolicyController { private final PolicyService service; // ❌ 禁止直接注入 Service } ``` ### 规则 2: Service 禁止注入其他 Service 这是**最常被违反的规则**。跨域数据需求必须上推到 Facade 层。 ```java // WRONG - Service 跨域调用 @Service public class AlgoServiceServiceImpl { private final LlmServiceMapper llmServiceMapper; // ❌ 注入其他域 Mapper private final VideoSourceService videoSourceService; // ❌ 注入其他 Service } // CORRECT - Facade 编排 @Component @RequiredArgsConstructor public class AlgoServiceFacade { private final AlgoServiceService algoServiceService; // ✅ private final LlmServiceService llmServiceService; // ✅ Facade 注入多个 Service public AlgoServiceDetail getDetail(Long id) { AlgoServiceDetail detail = algoServiceService.getDetail(id); if (detail.getLlmServiceId() != null) { LlmService llm = llmServiceService.getById(detail.getLlmServiceId()); detail.setLlmServiceName(llm.getName()); } return detail; } } ``` ### 规则 3: Mapper 保持空接口 查询逻辑在 Service 中使用 `LambdaQueryWrapper` 构建,保证类型安全。 **禁止** 在 Mapper 中新增方法或 Mapper XML 自定义 SQL,复杂条件仍在 Service 使用 Wrapper/`apply` 构建。 ```java // CORRECT @Mapper public interface PolicyMapper extends BaseMapper<AlertPolicy> { // 空接口,不添加任何方法 } // Service 中构建查询 LambdaQueryWrapper<AlertPolicy> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(AlertPolicy::getEnabled, true) .orderByDesc(AlertPolicy::getCreateTime); List<AlertPolicy> list = baseMapper.selectList(wrapper); // WRONG @Mapper public interface PolicyMapper extends BaseMapper<AlertPolicy> { @Select("SELECT * FROM alert_policy WHERE enabled = 1") // ❌ List<AlertPolicy> findEnabled(); } ``` ## 事务管理 ### 事务边界 | 场景 | 事务位置 | 示例 | |---|---|---| | 跨服务写操作 | Facade 层 | 创建任务 + 创建子任务 | | 单服务复杂写操作 | Service 层 | 批量删除 + 依赖检查 | | 读操作 | 无事务 | 查询列表、查询详情 | | Controller 层 | **禁止** | — | ### 事务注解标准写法 ```java @Transactional(rollbackFor = Exception.class) public Long create(TaskCreateReq req) { // 业务逻辑 } ``` ### 事务内禁止 - 远程调用(HTTP / RPC / 消息发送) - 耗时操作(文件 IO、大量计算) - `@Async` 方法调用 ## 异常处理体系 ### 异常层次 ``` RuntimeException └── BusinessException (业务异常,含 ErrorCode) └── AuthConsoleException (外部系统异常) ``` ### 各层异常职责 | 层 | 职责 | |---|---| | Service | 抛出 `BusinessException`(资源不存在、业务规则违反) | | Facade | **不捕获** BusinessException,透传给全局处理器;仅捕获需要补偿的外部调用异常 | | Controller | 不处理异常 | | GlobalExceptionHandler | 统一捕获,转换为 `ApiResponse` | ### 错误码分段管理 按业务模块分配错误码范围(如 2xxx 算法服务、3xxx 预警策略),避免冲突。 ### 日志级别规范 | 场景 | 级别 | 堆栈 | |---|---|---| | 业务异常(BusinessException) | WARN | 无 | | 参数校验失败 | WARN | 无 | | 系统异常(未预期) | ERROR | 有 | | 关键业务操作(创建/更新/删除) | INFO | 无 | ## 命名规范 ### Java 命名 | 类型 | 规则 | 示例 | |---|---|---| | 类名 | PascalCase | `AnalysisTaskService` | | 方法 / 变量 | camelCase | `getTaskById`, `videoSourceId` | | 常量 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` | | 包名 | 全小写 | `com.example.service.impl` | ### 分层命名 | 类型 | 命名模式 | |---|---| | Controller | `{Resource}Controller` | | Facade | `{Resource}Facade` (直接类,无接口) | | Service 接口 | `{Resource}Service` | | Service 实现 | `{Resource}ServiceImpl` | | Mapper | `{Resource}Mapper` | | Entity | `{Resource}` | | Converter | `{Resource}Converter` | ### 数据库命名 | 类型 | 规则 | 示例 | |---|---|---| | 表名 | snake_case | `alert_policy`, `video_source_cache` | | 字段名 | snake_case | `create_time`, `llm_service_id` | | 外键字段 | `{关联表}_id` | `policy_id`, `task_id` | | 唯一索引 | `uk_{fields}` | `uk_name_version` | | 普通索引 | `idx_{fields}` | `idx_create_time` | ### API 路径 - 格式: `/api/v{version}/{resources}` (复数, kebab-case) - 示例: `/api/v1/llm-services`, `/api/v1/analysis-tasks` ## 代码质量原则 ### 必须遵守 - 公共 API 方法必须有 Javadoc - 使用 `LambdaQueryWrapper` 保证类型安全,避免字符串列名 - 不使用物理外键约束,通过应用层保证数据一致性 - 所有表使用逻辑删除(`deleted` 字段) - 写操作考虑乐观锁(`version_num` 字段) - 删除前检查依赖关系,防止数据不一致 ### 统一响应格式 所有 API 返回 `ApiResponse<T>`: ```java ApiResponse.ok() // 无数据成功 ApiResponse.ok(data) // 带数据成功 ApiResponse.error(code, msg) // 错误 ``` ### 参数校验 - Request Body: `@Valid @RequestBody XxxReq req` - Path Variable 校验: 类上加 `@Validated`,参数上加 `@NotBlank` - 校验注解: `@NotBlank`, `@NotNull`, `@NotEmpty` (Jakarta Validation) ## 常见反模式 | 反模式 | 为什么不行 | 正确做法 | |---|---|---| | Service 注入其他 Service | 循环依赖、职责混乱、难以测试 | 跨域编排放 Facade 层 | | Controller 直接调用 Service | 跳过 Facade 编排层,业务逻辑散落 | Controller → Facade → Service | | Mapper 中写自定义 SQL | 丢失类型安全,SQL 散落 | Service 中用 LambdaQueryWrapper | | 事务内做 HTTP/RPC 调用 | 长事务、锁争用、调用失败导致回滚 | 事务外调用,或拆分事务 | | 捕获 BusinessException 后吞掉 | 错误被隐藏,调用方无法感知 | 让全局处理器统一处理 | | Entity 直接作为 API 响应 | 暴露内部结构,难以演化 | 使用 DTO 做 API 契约 | | 不指定 rollbackFor | 默认只回滚 RuntimeException | `@Transactional(rollbackFor = Exception.class)` | ## Checklist 编写前: - [ ] 已确认当前项目确实采用 Controller → Facade → Service → Mapper 分层 - [ ] 已识别当前改动属于单域逻辑还是跨域编排 - [ ] 已确认异常、响应、分页等公共模型的项目约定 完成后: - [ ] Controller 只注入 Facade - [ ] Service 未注入其他 Service 或其他域的 Mapper - [ ] 写操作的事务边界明确,且未放在 Controller - [ ] API 对外返回 DTO,而不是 Entity
عرض على GitHub