modelscope.cn

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.

Installation

$ npx skills add https://modelscope.cn

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from modelscope.cn · top by installs.

npx skills add https://modelscope.cn

Browse all from modelscope.cn

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,319 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

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

// 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 层。

// 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 构建。

// 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 层 禁止

事务注解标准写法

@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
常量 UPPERSNAKECASE MAXRETRYCOUNT
包名 全小写 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 alertpolicy, videosource_cache
字段名 snake_case createtime, llmservice_id
外键字段 {关联表}_id policyid, taskid
唯一索引 uk_{fields} uknameversion
普通索引 idx_{fields} idxcreatetime

API 路径

  • 格式: /api/v{version}/{resources} (复数, kebab-case)
  • 示例: /api/v1/llm-services, /api/v1/analysis-tasks

代码质量原则

必须遵守

  • 公共 API 方法必须有 Javadoc
  • 使用 LambdaQueryWrapper 保证类型安全,避免字符串列名
  • 不使用物理外键约束,通过应用层保证数据一致性
  • 所有表使用逻辑删除(deleted 字段)
  • 写操作考虑乐观锁(version_num 字段)
  • 删除前检查依赖关系,防止数据不一致

统一响应格式

所有 API 返回 ApiResponse<T>:

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