Kratos Development
aide-family/moon
Develops Go microservices with Kratos v2 following official design philosophy, DDD/Clean Architecture layout, Protobuf API, error/config/middleware patterns, and observability.
DDD 六边形架构设计与部署技能包。提供 Domain/Case/Infrastructure 层设计模式与代码模板,以及 Docker 环境部署脚本。当用户询问 DDD 架构、设计模式或需要部署项目时调用。
$ npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install fuzhengwei/xfg-ddd-skills xfg-ddd-skills --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
Claude Code skills documentation · loads skills from .claude/skills/
Install the "xfg-ddd-skills" agent skill from https://github.com/fuzhengwei/xfg-ddd-skills/tree/main into .claude/skills/xfg-ddd-skills/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "xfg-ddd-skills", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install fuzhengwei/xfg-ddd-skills xfg-ddd-skills --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "xfg-ddd-skills" agent skill from https://github.com/fuzhengwei/xfg-ddd-skills/tree/main into .agents/skills/xfg-ddd-skills/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "xfg-ddd-skills", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install fuzhengwei/xfg-ddd-skills xfg-ddd-skills --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "xfg-ddd-skills" agent skill from https://github.com/fuzhengwei/xfg-ddd-skills/tree/main into .cursor/skills/xfg-ddd-skills/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "xfg-ddd-skills", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install fuzhengwei/xfg-ddd-skills xfg-ddd-skills --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "xfg-ddd-skills" agent skill from https://github.com/fuzhengwei/xfg-ddd-skills/tree/main into .gemini/skills/xfg-ddd-skills/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "xfg-ddd-skills", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install fuzhengwei/xfg-ddd-skills xfg-ddd-skillsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "xfg-ddd-skills" agent skill from https://github.com/fuzhengwei/xfg-ddd-skills/tree/main into .github/skills/xfg-ddd-skills/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "xfg-ddd-skills", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install fuzhengwei/xfg-ddd-skills xfg-ddd-skills --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "xfg-ddd-skills" agent skill from https://github.com/fuzhengwei/xfg-ddd-skills/tree/main into .opencode/skills/xfg-ddd-skills/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "xfg-ddd-skills", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
xfg-ddd-skillsDDD 六边形架构设计与部署技能包。提供 Domain/Case/Infrastructure 层设计模式与代码模板,以及 Docker 环境部署脚本。当用户询问 DDD 架构、设计模式或需要部署项目时调用。
Xfg Ddd Skills is an agent skill from fuzhengwei/xfg-ddd-skills. DDD 六边形架构设计与部署技能包。提供 Domain/Case/Infrastructure 层设计模式与代码模板,以及 Docker 环境部署脚本。当用户询问 DDD 架构、设计模式或需要部署项目时调用。
Its SKILL.md is about 13k tokens, which your agent loads only when the skill is triggered. The skill folder holds 23 other files, including scripts and reference files (for example `README.md`, `references/aggregate.md` and `references/architecture.md`).
It sits in Development, covering Domain-driven design. It works with Docker. The repository describes itself as: ddd skills 一套配合AI工具,完整的 DDD 六边形架构工程搭建与开发解决方案。 @小傅哥. The licence is MIT.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit aca0123. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 1 file in scripts/, which the agent can run.
Shell commands in SKILL.md call:
dockerdocker-composemvncurlbashFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
github.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
MYSQL_ROOT_PASSWORDHTTP_PASSWORDMYSQL_PASSWORDRABBITMQ_PASSWORDFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Xfg Ddd Skills loads about 13k tokens when it runs, and up to ~77k if it reads all its reference files. Until then it costs about 30 tokens; SKILL.md has 1,124 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from fuzhengwei/xfg-ddd-skills at commit aca0123, republished under its MIT licence (© fuzhengwei). 1,124 words, ~13,202 tokens.
.claude/skills/xfg-ddd-skills/SKILL.md (or your agent's skills folder). This skill also uses 22 other files; get the full folder from GitHub.Design and implement software using Domain-Driven Design with Hexagonal Architecture. This skill provides patterns, templates, and best practices for building maintainable domain-centric applications.
当用户说"创建 DDD 项目"、"新建项目"、"创建项目"、"创建ddd项目"时,必须使用 scripts/create-ddd-project.sh 脚本。
脚本支持系统: Windows (Git Bash/MSYS2)、Mac (macOS)、Linux,自动检测并适配。
⚠️ 环境提醒: 建议提前安装 JDK 17+ 和 Maven 3.8.*,脚本启动时会自动检测并给出各平台安装指引,未安装也可继续但可能导致生成失败。
⚠️ 重要提醒:必须询问用户项目创建地址
在创建项目前,如果用户没有明确给出工程创建地址,必须询问用户在哪里创建项目。 不能随意创建到默认目录,必须获得用户确认。
示例对话:
用户:帮我创建一个 DDD 项目
AI:好的,我来帮您创建 DDD 项目。请问您希望将项目创建在哪个目录?
例如:
1) /Users/xxx/projects
2) /Users/xxx/Documents
3) /home/xxx/workspace
4) 其他路径(请直接输入)
用户:创建在 /Users/xxx/projects 下
AI:确认在 /Users/xxx/projects 下创建项目,开始执行...流程:
第一步:确认项目创建目录
必须询问用户,如果用户未指定,列出可选项供用户选择。
示例:
📂 选择项目生成目录
──────────────────────────────
1) /Users/xxx/projects
2) /Users/xxx/Documents
3) /home/xxx/workspace
4) 自定义路径(直接输入路径)
直接回车 = 选择 [1]第二步:填写项目配置(逐一询问,直接回车使用默认值)
| 参数 | 说明 | 默认值 | 示例 |
|---|---|---|---|
| GroupId | Maven 坐标 groupId,标识组织或公司 | com.yourcompany | cn.bugstack |
| ArtifactId | 项目模块唯一标识名称 | your-project-name | order-system |
| Version | 项目版本号 | 1.0.0-SNAPSHOT | 1.0.0-RELEASE |
| Package | Java 代码根包名 | 自动从 GroupId + ArtifactId 推导 | cn.bugstack.order |
| Archetype 版本 | 脚手架模板版本 | 1.8 | - |
第三步:确认并生成
显示所有配置,确认后执行 Maven Archetype 生成项目。
脚本执行方式(在 xfg-ddd-skills 项目根目录下运行):
bash scripts/create-ddd-project.sh⚠️ 必须先 cd 到
xfg-ddd-skills项目目录下再执行,脚本会自动定位自身路径。 AI 负责引导用户选择目录、填写参数,无需手动拼凑 Maven 命令。 ⚠️ 再次强调:创建项目前必须询问用户项目创建地址,不能随意创建!
| Task | Reference |
|---|---|
| Architecture overview | references/architecture.md |
| Entity design | references/entity.md |
| Aggregate design | references/aggregate.md |
| Value Object design | references/value-object.md |
| Repository pattern | references/repository.md |
| Port & Adapter | references/port-adapter.md |
| Domain Service | references/domain-service.md |
| Case layer orchestration | references/case-layer.md |
| Trigger layer | references/trigger-layer.md |
| Infrastructure layer | references/infrastructure-layer.md |
| Domain 层设计指南(避免常见错误) | references/domain-design-guide.md |
| Domain 层核心模式 | references/domain-patterns.md |
| Infrastructure 层核心模式 | references/infrastructure-patterns.md |
| DevOps 部署 | references/devops-deployment.md |
| Project structure | references/project-structure.md |
| Naming conventions | references/naming.md |
| Docker Images | references/docker-images.md |
┌─────────────────────────────────────────────────────────────┐
│ Trigger Layer │
│ (HTTP Controller / MQ Listener / Job) │
└─────────────────────────┬───────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ API Layer │
│ (DTO / Request / Response) │
└─────────────────────────┬───────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ Case Layer │
│ (Orchestration / Business Flow) │
└─────────────────────────┬───────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ Domain Layer │
│ (Entity / Aggregate / VO / Domain Service) │
└─────────────────────────┬───────────────────────────────────┘
▲
┌─────────────────────────────────────────────────────────────┐
│ Infrastructure Layer │
│ (Repository Impl / Port Adapter / DAO / PO) │
└─────────────────────────────────────────────────────────────┘Dependency Rule: Trigger → API → Case → Domain ← Infrastructure
在生成 Infrastructure 层代码前,AI 必须严格遵守以下结构规范。违反任何一条都是错误的。
{project}-infrastructure/src/main/java/
└── cn/{company}/infrastructure/
├── adapter/ # 适配器实现(实现 Domain 层定义的接口)
│ ├── port/ # Port 实现,调用 gateway/
│ │ └── {Xxx}Port.java
│ └── repository/ # Repository 实现,调用 dao/ 和 redis/
│ └── {Xxx}Repository.java
├── dao/ # MyBatis DAO 接口 + PO 对象
│ ├── po/ # PO 对象(数据库映射)
│ │ └── {Xxx}PO.java
│ └── I{Xxx}Dao.java # DAO 接口
├── redis/ # Redis 操作封装
│ └── IRedisService.java / RedisService.java
├── gateway/ # HTTP/RPC 客户端
│ ├── dto/ # 远程调用 DTO
│ │ ├── {Xxx}RequestDTO.java
│ │ └── {Xxx}ResponseDTO.java
│ └── {Xxx}GatewayService.java # HTTP 服务客户端
└── config/ # Spring 配置类(线程池、OkHttp 等)| 错误包名 | 错误示例 | 正确位置 |
|---|---|---|
persistent/ | infrastructure.persistent.repository.XxxRepository | ❌ 禁止! 应放在 adapter/repository/ |
persistent/repository/ | infrastructure.persistent.repository.XxxRepository | ❌ 禁止! 应放在 adapter/repository/ |
persistent/dao/ | infrastructure.persistent.dao.IXxxDao | ❌ 禁止! 应放在 dao/ |
persistent/po/ | infrastructure.persistent.po.XxxPO | ❌ 禁止! 应放在 dao/po/ |
scenario/ | infrastructure.scenario.XxxScenario | ❌ 禁止! DAO 操作只能放在 dao/ |
config/ 下放 Redis 操作 | config.RedisConfig.setValue() | ❌ 禁止! Redis 操作放 redis/ |
adapter/repository/,不放 persistent/、repository/(根目录)dao/ 和 dao/po/,不放 persistent/dao/、persistent/po/redis/,不放 config/gateway/,不放 adapter/gateway/persistent 包 — 这个包名在本架构中不存在// ❌ 错误1:创建 persistent 包放 Repository
infrastructure/persistent/repository/UserRepository.java
// ✅ 正确:infrastructure/adapter/repository/UserRepository.java
// ❌ 错误2:创建 persistent 包放 DAO 和 PO
infrastructure/persistent/dao/IUserDao.java
infrastructure/persistent/dao/po/UserPO.java
// ✅ 正确:infrastructure/dao/IUserDao.java
// ✅ 正确:infrastructure/dao/po/UserPO.java
// ❌ 错误3:在 config 包下写 Redis 操作
infrastructure/config/RedisConfig.java // 内部包含 setValue() 等操作方法
// ✅ 正确:Redis 操作放 infrastructure/redis/RedisService.java
// ✅ 正确:config/ 只放 Bean 配置(如 RedisTemplate 的序列化配置)在生成 Domain 层代码前,必须逐项检查:
1. 是否有多种处理方式(if-else 判断类型)?
→ 是:使用策略模式(IXxxStrategy 接口 + 实现类 + Map<String, IXxxStrategy> 注入)
2. 是否有多个独立的校验/过滤步骤(3步以上)?
→ 是:使用责任链模式(IXxxFilter 接口 + Factory 组装链)
3. Service 方法是否超过 60 行? → 是:拆分为过滤器(校验)+ 策略(执行)+ 私有方法(保存)
4. Infrastructure 层是否包含业务判断逻辑? → 是:将业务校验移到 Domain 层的过滤器中,Infrastructure 只做数据读写
5. 是否跨域直接依赖另一个 Domain 的 Repository? → 是:通过 Case 层编排,或在本域 Repository 接口中聚合所需数据
6. Infrastructure 包名是否正确?
→ Repository 实现:adapter/repository/(❌ 不是 persistent/repository/)
→ DAO 操作:dao/(❌ 不是 scenario/dao/、persistent/dao/ 或其他包)
→ PO 对象:dao/po/(❌ 不是 persistent/po/、persistent/dao/po/ 或其他包)
→ Redis 操作:redis/(❌ 不是 config/)
→ ⚠️ 永远不要创建 persistent 包 — 这个包名在本架构中不存在,是严格禁止的
7. Domain 与 Infrastructure 的通信路径是否正确?
→ 唯一合法路径:Domain 层 → adapter/port/ 或 adapter/repository/(接口定义在 Domain,实现在 Infrastructure)
→ ❌ Domain 层不允许直接依赖 dao/、redis/、gateway/ 等基础设施包
→ ❌ 不允许在 adapter/ 之外新建包做跨层通信
8. Infrastructure 内部调用链是否正确?
→ adapter/port/ 只能调用 gateway/(HTTP/RPC 客户端)
→ adapter/repository/ 只能调用 dao/(数据库)、redis/(缓存)
→ ❌ adapter/port/ 不允许直接调用 dao/ 或 redis/
→ ❌ adapter/repository/ 不允许直接调用 gateway/
→ ❌ 不允许在 adapter/、dao/、redis/、gateway/、config/ 之外新增基础设施包
六边形架构的核心约束:Domain 层与 Infrastructure 层之间,只能通过
adapter适配器进行通信,不允许任何绕行路径。
┌──────────────────────────────────────────────────────────────────┐
│ Domain 层 │
│ │
│ domain/{domain}/adapter/ │
│ ├── port/ │
│ │ └── I{Xxx}Port.java ← 定义远程调用接口 │
│ └── repository/ │
│ └── I{Xxx}Repository.java ← 定义数据访问接口 │
│ │
│ domain/{domain}/service/ │
│ └── {Xxx}ServiceImpl.java ← 业务逻辑只依赖上面的接口 │
└──────────────────────────┬───────────────────────────────────────┘
│ 依赖倒置(Domain 定义接口)
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ Infrastructure 层 │
│ │
│ infrastructure/adapter/ ← ✅ 唯一合法的通信桥梁 │
│ ├── port/{Xxx}Port.java 实现 IPort,调用 gateway/ │
│ └── repository/{Xxx}Repository.java 实现 IRepository,调用 │
│ dao/ 和 redis/ │
│ │
│ infrastructure/dao/ ← 被 repository 调用 │
│ infrastructure/redis/ ← 被 repository 调用 │
│ infrastructure/gateway/ ← 被 port 调用 │
│ infrastructure/config/ ← Spring 配置,不参与通信 │
└──────────────────────────────────────────────────────────────────┘adapter/port/ ──────调用──────→ gateway/ (HTTP/RPC 客户端)
└── gateway/dto/ (请求/响应DTO)
adapter/repository/ ─调用──→ dao/ (MyBatis DAO + PO)
─调用──→ redis/ (Redis 操作封装)| 违规行为 | 说明 | 后果 |
|---|---|---|
Domain 直接依赖 dao/ | Domain Service 直接注入 IXxxDao | 违反依赖倒置,Domain 耦合 MyBatis |
Domain 直接依赖 redis/ | Domain Service 直接注入 RedisService | 违反依赖倒置,Domain 耦合 Redis |
Domain 直接依赖 gateway/ | Domain Service 直接注入 XxxGateway | 违反依赖倒置,Domain 耦合 HTTP |
adapter/ 之外新建通信包 | 在 infrastructure/ 下新建 service/、handler/、manager/ 等包做跨层通信 | 破坏六边形架构边界 |
adapter/port/ 直接调用 dao/ | Port 实现中直接操作数据库 | 职责混乱,Port 应只负责远程调用 |
adapter/repository/ 直接调用 gateway/ | Repository 实现中直接发起 HTTP 请求 | 职责混乱,Repository 应只负责本地数据 |
| 任意新增基础设施包 | 在 adapter/、dao/、redis/、gateway/、config/ 之外新增包 | 破坏架构规范,不允许 |
Domain 定接口,Infra 来实现
通信只过 adapter,port 和 repository
port 对 gateway,repository 对 dao + redis
不绕行、不越权、不乱加包model/
├── aggregate/ # 聚合对象
│ └── XxxAggregate.java
├── entity/ # 实体对象
│ ├── XxxEntity.java # 普通实体
│ └── XxxCommandEntity.java # 命令实体
└── valobj/ # 值对象
├── XxxVO.java # 普通值对象
└── XxxEnumVO.java # 枚举值对象⚠️ 注意:model/ 下没有单独的 command/ 包,命令实体统一放在 entity/ 包下。
当用户需要实现一个新功能时,必须按照以下分层调用流程进行开发:
┌─────────────────────────────────────────────────────────────────────────┐
│ 新功能开发流程 │
└─────────────────────────────────────────────────────────────────────────┘
外部请求
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 1. Trigger 层(触发层) │
│ 职责:接收外部请求,路由转发,参数校验,不含业务逻辑 │
│ │
│ • HTTP Controller → 接收 HTTP 请求 │
│ • MQ Listener → 监听消息队列 │
│ • Job/Task → 定时任务/异步任务 │
│ │
│ 输出:调用 Case 层接口,或轻量场景直接调用 Domain 层 │
└─────────────────────────┬───────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 2. Case 层(编排层)- 可选,复杂业务需要 │
│ 职责:跨领域业务编排,流程串联,事务管理 │
│ │
│ • 接收 Trigger 调用 │
│ • 编排多个 Domain Service 调用顺序 │
│ • 处理跨领域数据转换 │
│ • 管理分布式事务(如需要) │
│ │
│ 输出:调用 Domain 层 Service 接口 │
└─────────────────────────┬───────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 3. Domain 层(领域层) │
│ 职责:核心业务逻辑,业务规则校验,领域模型操作 │
│ │
│ • Service 服务实现业务逻辑 │
│ • Entity/Aggregate 封装业务行为 │
│ • 通过 Adapter 接口(Port/Repository)与外部交互 │
│ │
│ 注意:Domain 层不直接依赖 Infrastructure,只依赖接口 │
│ │
│ 输出:调用 Adapter 接口(定义在 domain/adapter/ 下) │
└─────────────────────────┬───────────────────────────────────────────────┘
│ 依赖倒置:Domain 定义接口,Infrastructure 实现
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 4. Infrastructure 层(基础设施层) │
│ 职责:技术实现,数据持久化,外部服务调用 │
│ │
│ • adapter/repository/ → 实现 Repository 接口,操作数据库 │
│ • adapter/port/ → 实现 Port 接口,调用外部 HTTP/RPC 服务 │
│ • dao/ → MyBatis DAO 接口和 PO 对象 │
│ • gateway/ → HTTP/RPC 客户端,远程服务调用 │
│ • redis/ → Redis 操作 │
│ │
│ 输出:返回数据给 Domain 层,或执行外部调用 │
└─────────────────────────────────────────────────────────────────────────┘| 层级 | 职责 | 禁止做的事 | 依赖方向 |
|---|---|---|---|
| Trigger | 接收请求、参数校验、路由转发 | 业务逻辑、直接操作数据库 | → API/Case/Domain |
| Case | 跨域编排、流程串联、事务管理 | 直接操作数据库、外部 HTTP 调用 | → Domain |
| Domain | 业务规则、领域模型、逻辑编排 | 直接依赖 MyBatis/Redis/HTTP | → 只依赖接口 |
| Infrastructure | 数据持久化、外部调用、技术实现 | 业务判断、业务规则 | 实现 Domain 接口 |
当用户说"帮我实现一个 XXX 功能"时,按以下顺序检查:
询问用户或根据需求判断:
□ HTTP API 接口? → 创建 Controller
□ MQ 消息监听? → 创建 MQ Listener
□ 定时任务? → 创建 Job
□ 异步任务? → 创建 Task/Worker□ 涉及多个领域协作? → 需要 Case 层
□ 业务流程超过 3 步? → 需要 Case 层
□ 需要分布式事务? → 需要 Case 层
□ 单领域、简单业务? → Trigger 直接调用 Domain□ 定义 Entity/Aggregate/VO
□ 定义 Service 接口和实现
□ 定义 Repository 接口(数据访问)
□ 定义 Port 接口(外部调用,如需要)□ 实现 Repository 接口(adapter/repository/)
□ 创建 DAO 接口和 PO 对象(dao/)
□ 实现 Port 接口(adapter/port/,如需要)
□ 创建 Gateway 客户端(gateway/,如需要)
□ 配置 Redis 操作(redis/,如需要)以"订单支付"功能为例,展示完整分层调用:
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Resource
private IOrderPayCase orderPayCase; // 复杂业务,调用 Case 层
@PostMapping("/pay")
public Response<OrderPayResponse> pay(@RequestBody OrderPayRequest request) {
// 1. 参数校验
if (request.getOrderId() == null || request.getPayAmount() == null) {
return Response.fail("参数不完整");
}
// 2. 调用 Case 层(复杂业务)
// 如果是简单业务,可直接调用 Domain Service
try {
OrderPayResult result = orderPayCase.execute(request);
return Response.success(convertToResponse(result));
} catch (Exception e) {
return Response.fail(e.getMessage());
}
}
}public interface IOrderPayCase {
OrderPayResult execute(OrderPayRequest request) throws Exception;
}
@Service
public class OrderPayCaseImpl implements IOrderPayCase {
@Resource
private IOrderService orderService; // 订单领域服务
@Resource
private IPaymentService paymentService; // 支付领域服务
@Resource
private IInventoryService inventoryService; // 库存领域服务
@Override
@Transactional(rollbackFor = Exception.class)
public OrderPayResult execute(OrderPayRequest request) throws Exception {
log.info("执行订单支付流程,订单号:{}", request.getOrderId());
// 1. 查询订单
OrderEntity order = orderService.queryOrder(request.getOrderId());
// 2. 扣减库存(调用库存领域服务)
inventoryService.deduct(order.getProductId(), order.getQuantity());
// 3. 执行支付(调用支付领域服务)
PaymentResult payment = paymentService.pay(order, request.getPayAmount());
// 4. 更新订单状态(调用订单领域服务)
orderService.markPaid(order.getOrderId(), payment.getTransactionId());
// 5. 返回结果
return OrderPayResult.builder()
.orderId(order.getOrderId())
.status("PAID")
.transactionId(payment.getTransactionId())
.build();
}
}// 订单领域服务接口
public interface IOrderService {
OrderEntity queryOrder(String orderId);
void markPaid(String orderId, String transactionId);
}
// 订单领域服务实现
@Service
public class OrderServiceImpl implements IOrderService {
@Resource
private IOrderRepository orderRepository; // 依赖 Repository 接口,非实现
@Override
public OrderEntity queryOrder(String orderId) {
return orderRepository.queryById(orderId);
}
@Override
public void markPaid(String orderId, String transactionId) {
OrderEntity order = orderRepository.queryById(orderId);
// 业务规则校验
if (order.getStatus() != OrderStatus.PENDING_PAY) {
throw new BusinessException("订单状态不正确,无法支付");
}
// 执行业务逻辑
order.pay(transactionId); // Entity 封装业务行为
orderRepository.save(order);
}
}
// 支付领域服务
public interface IPaymentService {
PaymentResult pay(OrderEntity order, BigDecimal amount);
}
@Service
public class PaymentServiceImpl implements IPaymentService {
@Resource
private IPaymentPort paymentPort; // 依赖 Port 接口,调用外部支付网关
@Override
public PaymentResult pay(OrderEntity order, BigDecimal amount) {
// 构建支付请求
PaymentRequest request = PaymentRequest.builder()
.orderId(order.getOrderId())
.amount(amount)
.build();
// 调用外部支付服务(通过 Port 接口)
return paymentPort.executePayment(request);
}
}// Repository 实现 - 订单数据访问
@Repository
public class OrderRepositoryImpl implements IOrderRepository {
@Resource
private IOrderDao orderDao; // MyBatis DAO
@Resource
private StringRedisTemplate redisTemplate;
@Override
public OrderEntity queryById(String orderId) {
// 先查缓存
String cacheKey = "order:" + orderId;
String cached = redisTemplate.opsForValue().get(cacheKey);
if (cached != null) {
return JSON.parseObject(cached, OrderEntity.class);
}
// 再查数据库
OrderPO po = orderDao.queryById(orderId);
OrderEntity entity = convertToEntity(po);
// 写入缓存
redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(entity), 30, TimeUnit.MINUTES);
return entity;
}
@Override
public void save(OrderEntity entity) {
OrderPO po = convertToPO(entity);
orderDao.update(po);
// 更新缓存
redisTemplate.opsForValue().set("order:" + entity.getOrderId(),
JSON.toJSONString(entity), 30, TimeUnit.MINUTES);
}
}
// Port 实现 - 外部支付网关调用
@Component
public class PaymentPortImpl implements IPaymentPort {
@Resource
private PaymentGateway paymentGateway; // HTTP 客户端
@Override
public PaymentResult executePayment(PaymentRequest request) {
// 调用外部支付服务
PaymentGatewayRequest gatewayRequest = convertToGatewayRequest(request);
PaymentGatewayResponse response = paymentGateway.pay(gatewayRequest);
if (!response.isSuccess()) {
throw new PaymentException("支付失败:" + response.getErrorMsg());
}
return PaymentResult.builder()
.transactionId(response.getTransactionId())
.status("SUCCESS")
.build();
}
}// 错误示例
@RestController
public class OrderController {
@Resource
private IOrderRepository orderRepository; // ❌ 直接依赖 Repository
@PostMapping("/order")
public Response create(@RequestBody OrderRequest request) {
// 业务逻辑散落在 Controller
OrderEntity order = new OrderEntity();
order.setStatus("CREATED");
orderRepository.save(order); // ❌ 直接操作数据库
return Response.success();
}
}纠正:Trigger 层只负责接收请求和路由,业务逻辑应下沉到 Domain 层。
// 错误示例
@Service
public class OrderServiceImpl implements IOrderService {
@Resource
private IOrderDao orderDao; // ❌ 直接依赖 DAO,违反分层
public OrderEntity queryOrder(String orderId) {
OrderPO po = orderDao.queryById(orderId); // ❌ 直接操作数据库
return convert(po);
}
}纠正:Domain 层应依赖 Repository 接口,由 Infrastructure 层实现。
// 错误示例
@Repository
public class OrderRepositoryImpl implements IOrderRepository {
public void save(OrderEntity entity) {
// ❌ 在 Repository 中做业务判断
if (entity.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new BusinessException("金额必须大于0"); // 业务异常不应在这里抛
}
orderDao.update(convertToPO(entity));
}
}纠正:业务判断应在 Domain 层完成,Infrastructure 层只负责数据读写。
// 错误示例
@Service
public class OrderServiceImpl implements IOrderService {
@Resource
private IInventoryRepository inventoryRepository; // ❌ 跨域依赖 Repository
public void createOrder(OrderEntity order) {
// 直接操作库存领域的数据
InventoryPO inventory = inventoryRepository.queryByProductId(order.getProductId());
// ...
}
}纠正:跨域操作应通过 Case 层编排,或调用目标领域的 Service 接口。
Trigger 只路由,Case 做编排
Domain 管业务,Infra 做实现
接口定义在 Domain,实现放在 Infra 层
依赖永远向内指,Domain 是核心当用户需要增加新功能时,按照以下决策流程进行开发:
用户需要新功能
│
▼
┌───────────────────┐
│ 检查现有领域服务 │ ──是──→ 扩展现有 Service
│ domain/xxx/service│
│ 是否有支持? │
└─────────┬─────────┘
│否
▼
┌───────────────────┐
│ 创建新的领域? │ ──是──→ 创建新领域(完整结构)
│ domain/xxx/ │
│ │
└─────────┬─────────┘
│
▼
┌───────────────────┐
│ Case 层是否需要? │ ──是──→ 创建 Case 层编排
│ 业务复杂?多领域? │
└─────────┬─────────┘
│否(轻量工程)
▼
┌───────────────────┐
│ Trigger 直接调用 │ ←── Trigger → Domain
│ Domain 领域层 │
└───────────────────┘| 问题 | 答案 | 处理方式 |
|---|---|---|
| 现有领域能否支持新功能? | ✅ 是 | 在现有 Service 中添加方法 |
| 是否需要跨多个领域? | ✅ 是 | 创建 Case 层编排 |
| 业务逻辑是否复杂? | ✅ 是 | 创建 Case 层编排 |
| 是否是轻量工程? | ✅ 是 | Trigger 直接调用 Domain |
| Trigger 是否越来越复杂? | ✅ 是 | 询问用户是否创建 Case 层 |
判断条件:新功能属于现有领域的业务范围。
开发步骤:
检查现有领域服务
domain/{domain}/service/ 目录扩展现有 Service
示例:在交易域添加一个"查询订单列表"功能
// 1. 在现有接口中添加方法
public interface ITradeRepository {
// 现有方法...
// 新增:查询订单列表
List<MarketPayOrderEntity> queryOrderList(QueryOrderRequest request);
}
// 2. 在实现类中实现
@Repository
public class TradeRepository implements ITradeRepository {
@Resource
private IMcpGatewayDao mcpGatewayDao;
@Override
public List<MarketPayOrderEntity> queryOrderList(QueryOrderRequest request) {
// 实现查询逻辑
}
}判断条件:新功能涉及全新的业务领域,与现有领域无关。
开发步骤:
创建完整的领域结构
domain/
└── {new-domain}/ # 新领域
├── adapter/ # 适配器接口
│ ├── port/ # 端口接口
│ │ └── I{Xxx}Port.java
│ └── repository/ # 仓储接口
│ └── I{Xxx}Repository.java
├── model/ # 领域模型
│ ├── aggregate/ # 聚合根
│ ├── entity/ # 实体
│ └── valobj/ # 值对象
└── service/ # 领域服务
├── I{Xxx}Service.java # 服务接口
└── {能力}/
└── {Xxx}ServiceImpl.java定义 Adapter 接口
// Repository 接口
public interface I{Xxx}Repository {
XxxEntity queryById(Long id);
void save(XxxEntity entity);
}
// Port 接口
public interface I{Xxx}Port {
void notify(XxxEntity entity) throws Exception;
}定义 Model
// 实体
@Data
public class XxxEntity {
private Long id;
private String name;
}
// 值对象
@Getter
public enum XxxStatusEnumVO {
CREATED("created", "已创建"),
PROCESSING("processing", "处理中"),
COMPLETED("completed", "已完成");
private String code;
private String info;
}实现 Service
public interface I{Xxx}Service {
void process(XxxEntity entity) throws Exception;
}
@Slf4j
@Service
public class XxxServiceImpl implements I{Xxx}Service {
@Resource
private I{Xxx}Repository repository;
@Resource
private I{Xxx}Port port;
@Override
public void process(XxxEntity entity) throws Exception {
log.info("处理业务:{}", entity.getId());
// 业务逻辑
repository.save(entity);
port.notify(entity);
}
}判断条件:业务涉及多个领域协作,或需要编排多个领域服务。
开发步骤:
创建 Case 模块结构
case/
└── {domain}/
└── {capability}/
├── I{Xxx}Case.java # Case 接口
└── impl/
└── {Xxx}CaseImpl.java # Case 实现定义 Case 接口
/**
* XXX 业务编排接口
*
* 职责:编排多个领域服务,完成复杂业务场景
*/
public interface I{Xxx}Case {
/**
* 执行 XXX 业务
*/
void execute(XxxRequest request) throws Exception;
}实现 Case 编排
/**
* XXX 业务编排实现
*
* @author xiaofuge
*/
@Slf4j
@Service
public class XxxCaseImpl implements I{Xxx}Case {
@Resource
private IDomain1Service domain1Service;
@Resource
private IDomain2Service domain2Service;
@Override
public void execute(XxxRequest request) throws Exception {
log.info("执行 XXX 业务");
// 1. 调用领域服务1
Domain1Result r1 = domain1Service.method1(request.getParam1());
// 2. 调用领域服务2
domain2Service.method2(r1.getData());
// 3. 组装结果
// ...
}
}Case 层命名规范:
I{Xxx}Case{Xxx}CaseImpl判断条件:轻量工程,业务简单,不需要 Case 层编排。
开发步骤:
在 Trigger 层直接调用 Domain
@RestController
@RequestMapping("/api/xxx")
public class XxxController {
@Resource
private I{Xxx}Service xxxService;
@PostMapping("/process")
public Response<XxxResponse> process(@RequestBody XxxRequest request) {
try {
xxxService.process(request.toEntity());
return Response.success();
} catch (Exception e) {
return Response.fail(e.getMessage());
}
}
}Trigger 层职责
判断条件:Trigger 层代码越来越复杂,包含大量业务逻辑。
警告信号:
重构步骤:
询问用户
AI:检测到 Trigger 层代码比较复杂,是否需要创建 Case 层来分摊业务逻辑?
这样可以:
1. 将业务逻辑从 Controller 移到 Case 层
2. 提高代码可测试性
3. 更好的职责分离创建 Case 层
简化 Trigger 层
// 重构前
@RestController
public class XxxController {
@Resource private IDomain1Service d1;
@Resource private IDomain2Service d2;
@Resource private IDomain3Service d3;
public Response process(Request req) {
// 100+ 行业务逻辑...
}
}
// 重构后
@RestController
public class XxxController {
@Resource private I{Xxx}Case xxxCase;
public Response process(Request req) {
xxxCase.execute(req);
return Response.success();
}
}需求:在拼团系统中添加"订单超时取消"功能
步骤 1:检查现有领域
trade/
├── adapter/repository/ITradeRepository.java ← 可以复用
├── model/entity/TradeLockRuleCommandEntity.java
└── service/
├── lock/TradeLockOrderService.java ← 部分相关
└── refund/TradeRefundOrderService.java ← 退单逻辑可参考步骤 2:决策
步骤 3:实现
// 1. 扩展 ITradeRepository
public interface ITradeRepository {
// 现有方法...
// 新增:查询超时未支付订单
List<MarketPayOrderEntity> queryTimeoutUnpaidOrders();
// 新增:取消订单
void cancelOrder(String orderId);
}
// 2. 扩展 TradeLockOrderService
public interface ITradeLockOrderService {
// 现有方法...
// 新增:处理超时订单
void handleTimeoutOrders();
}
@Slf4j
@Service
public class TradeLockOrderService implements ITradeLockOrderService {
@Resource
private ITradeRepository repository;
@Override
public void handleTimeoutOrders() {
log.info("处理超时未支付订单");
// 1. 查询超时订单
List<MarketPayOrderEntity> orders = repository.queryTimeoutUnpaidOrders();
// 2. 遍历取消
for (MarketPayOrderEntity order : orders) {
repository.cancelOrder(order.getOrderId());
}
}
}步骤 4:添加 Trigger
@Component
public class OrderTimeoutJob {
@Resource
private ITradeLockOrderService tradeLockOrderService;
@Scheduled(cron = "0 */5 * * * ?") // 每5分钟执行
public void execute() {
try {
tradeLockOrderService.handleTimeoutOrders();
} catch (Exception e) {
log.error("订单超时处理异常", e);
}
}
}| 场景 | 判断条件 | 实现位置 |
|---|---|---|
| 扩展现有服务 | 功能属于现有领域 | domain/{domain}/service/ |
| 创建新领域 | 全新业务领域 | 创建完整的 domain/{new}/ 结构 |
| 创建 Case 层 | 多领域协作、复杂业务 | case/{domain}/{capability}/ |
| Trigger 调用 | 轻量工程、简单业务 | trigger/{domain}/controller/ |
| 重构为 Case | Trigger 越来越复杂 | 询问用户后重构 |
核心原则:
@Data @Builder @AllArgsConstructor @NoArgsConstructor
public class GroupBuyOrderAggregate {
/** 用户实体对象 */
private UserEntity userEntity;
/** 支付活动实体对象 */
private PayActivityEntity payActivityEntity;
/** 支付优惠实体对象 */
private PayDiscountEntity payDiscountEntity;
/** 已参与拼团量 */
private Integer userTakeOrderCount;
}@Data @Builder @AllArgsConstructor @NoArgsConstructor
public class MarketPayOrderEntity {
private String teamId;
private String orderId;
private BigDecimal originalPrice;
private BigDecimal deductionPrice;
private BigDecimal payPrice;
private TradeOrderStatusEnumVO tradeOrderStatusEnumVO;
}/** 命令实体放在 entity 包,使用 CommandEntity 后缀 */
@Data @Builder @AllArgsConstructor @NoArgsConstructor
public class TradeLockRuleCommandEntity {
private String userId;
private Long activityId;
private String teamId;
}@Getter @Builder @AllArgsConstructor @NoArgsConstructor
public class NotifyConfigVO {
private NotifyTypeEnumVO notifyType;
private String notifyMQ;
private String notifyUrl;
}@Getter @AllArgsConstructor
public enum RefundTypeEnumVO {
UNPAID_UNLOCK("unpaid_unlock", "Unpaid2RefundStrategy", "未支付,未成团") {
@Override
public boolean matches(GroupBuyOrderEnumVO groupBuyOrderEnumVO, TradeOrderStatusEnumVO tradeOrderStatusEnumVO) {
return GroupBuyOrderEnumVO.PROGRESS.equals(groupBuyOrderEnumVO)
&& TradeOrderStatusEnumVO.CREATE.equals(tradeOrderStatusEnumVO);
}
},
PAID_UNFORMED("paid_unformed", "Paid2RefundStrategy", "已支付,未成团") {
@Override
public boolean matches(GroupBuyOrderEnumVO groupBuyOrderEnumVO, TradeOrderStatusEnumVO tradeOrderStatusEnumVO) {
return GroupBuyOrderEnumVO.PROGRESS.equals(groupBuyOrderEnumVO)
&& TradeOrderStatusEnumVO.COMPLETE.equals(tradeOrderStatusEnumVO);
}
};
private String code;
private String strategy;
private String info;
public abstract boolean matches(GroupBuyOrderEnumVO groupBuyOrderEnumVO, TradeOrderStatusEnumVO tradeOrderStatusEnumVO);
public static RefundTypeEnumVO getRefundStrategy(GroupBuyOrderEnumVO g, TradeOrderStatusEnumVO t) {
return Arrays.stream(values()).filter(v -> v.matches(g, t)).findFirst()
.orElseThrow(() -> new RuntimeException("不支持的退款状态组合"));
}
}/** 1. 定义服务接口 */
public interface ITradeLockOrderService {
MarketPayOrderEntity lockMarketPayOrder(UserEntity user, PayActivityEntity activity, PayDiscountEntity discount) throws Exception;
}
/** 2. 实现服务(放在子包中) */
@Slf4j @Service
public class TradeLockOrderService implements ITradeLockOrderService {
@Resource private ITradeRepository repository;
@Resource private BusinessLinkedList<TradeLockRuleCommandEntity, TradeLockRuleFilterFactory.DynamicContext, TradeLockRuleFilterBackEntity> tradeRuleFilter;
@Override
public MarketPayOrderEntity lockMarketPayOrder(UserEntity userEntity, PayActivityEntity payActivityEntity, PayDiscountEntity payDiscountEntity) throws Exception {
log.info("锁定营销优惠支付订单:{} activityId:{}", userEntity.getUserId(), payActivityEntity.getActivityId());
// 1. 交易规则过滤(责任链)
TradeLockRuleFilterBackEntity back = tradeRuleFilter.apply(TradeLockRuleCommandEntity.builder()
.activityId(payActivityEntity.getActivityId())
.userId(userEntity.getUserId())
.teamId(payActivityEntity.getTeamId()).build(),
new TradeLockRuleFilterFactory.DynamicContext());
// 2. 构建聚合对象
GroupBuyOrderAggregate aggregate = GroupBuyOrderAggregate.builder()
.userEntity(userEntity)
.payActivityEntity(payActivityEntity)
.payDiscountEntity(payDiscountEntity)
.userTakeOrderCount(back.getUserTakeOrderCount())
.build();
// 3. 锁定聚合订单
return repository.lockMarketPayOrder(aggregate);
}
}/** 1. 策略接口 */
public interface IRefundOrderStrategy {
void refundOrder(TradeRefundOrderEntity entity) throws Exception;
void reverseStock(TeamRefundSuccess success) throws Exception;
}
/** 2. 抽象基类(模板方法) */
@Slf4j
public abstract class AbstractRefundOrderStrategy implements IRefundOrderStrategy {
@Resource protected ITradeRepository repository;
@Resource protected ThreadPoolExecutor threadPoolExecutor;
protected void doReverseStock(TeamRefundSuccess s, String type) throws Exception {
log.info("退单恢复锁单量 - {}", type);
repository.refund2AddRecovery(s.getActivityId() + ":" + s.getTeamId(), s.getOrderId());
}
}
/** 3. 具体策略 */
@Slf4j @Service("paid2RefundStrategy")
public class Paid2RefundStrategy extends AbstractRefundOrderStrategy {
@Override
public void refundOrder(TradeRefundOrderEntity e) throws Exception {
log.info("退单-已支付,未成团 userId:{}", e.getUserId());
NotifyTaskEntity n = repository.paid2Refund(GroupBuyRefundAggregate.buildPaid2RefundAggregate(e, -1, -1));
if (n != null) threadPoolExecutor.execute(() -> tradeTaskService.execNotifyJob(n));
}
@Override
public void reverseStock(TeamRefundSuccess s) throws Exception {
doReverseStock(s, "已支付,但有锁单记录,恢复锁单库存");
}
}| Principle | Description |
|---|---|
| Dependency Inversion | Domain defines interfaces, Infrastructure implements |
| Rich Domain Model | Entity contains both data and behavior |
| Aggregate Boundary | Transaction consistency inside, eventual consistency outside |
| Anti-Corruption Layer | Use Port to isolate external systems |
| Lightweight Trigger | Trigger layer only routes requests, no business logic |
Use DDD when:
Don't use DDD when:
当用户需要部署 DDD 项目时,按照以下流程执行:
cd /path/to/project
mvn clean package -Dmaven.test.skip=true# 使用阿里云加速镜像
docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:17-jdk-slim
docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.0.32
docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:6.2cd docs/dev-ops
docker-compose -f docker-compose-environment-aliyun.yml up -d mysql
# 等待 MySQL 就绪后初始化数据库
docker exec -it mysql mysql -uroot -p123456 -e "source /docker-entrypoint-initdb.d/xxx.sql"cd ai-mcp-gateway-app
docker build -t system/{artifactId}:1.0.0 .cd docs/dev-ops
docker-compose -f docker-compose-app.yml up -d# 查看容器状态
docker ps -a | grep {artifactId}
# 查看应用日志
docker logs -f {artifactId}
# 健康检查
curl http://localhost:{port}/actuator/health{project}/
├── docs/
│ └── dev-ops/
│ ├── docker-compose-environment-aliyun.yml # 基础环境(MySQL/Redis/RabbitMQ)
│ ├── docker-compose-app.yml # 应用服务
│ ├── mysql/
│ │ ├── my.cnf # MySQL 配置
│ │ └── sql/
│ │ └── {project}.sql # 数据库初始化脚本
│ ├── redis/
│ │ └── redis.conf # Redis 配置
│ ├── app/
│ │ ├── start.sh # 启动脚本
│ │ └── stop.sh # 停止脚本
│ └── README.md # 部署说明
├── {project}-app/
│ ├── Dockerfile # 应用 Dockerfile
│ ├── pom.xml
│ └── src/main/resources/
│ ├── application.yml
│ ├── application-dev.yml
│ ├── application-test.yml
│ ├── application-prod.yml
│ └── logback-spring.xml# 基础镜像
FROM registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:17-jdk-slim
# 作者
MAINTAINER xiaofuge
# 时区配置
ENV TZ=PRC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 添加应用 JAR
ADD target/{artifactId}.jar /{artifactId}.jar
# 暴露端口
EXPOSE {port}
# 启动命令
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /{artifactId}.jar $PARAMS"]version: '3.8'
services:
{artifactId}:
image: system/{artifactId}:1.0.0
container_name: {artifactId}
restart: on-failure
ports:
- "{port}:{port}"
environment:
- TZ=PRC
- SERVER_PORT={port}
- SPRING_PROFILES_ACTIVE=prod
volumes:
- ./logs:/data/log
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- my-network
depends_on:
- mysql
- redis
networks:
my-network:
driver: bridgeversion: '3.9'
services:
# MySQL 8.0
mysql:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.0.32
container_name: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
ports:
- "13306:3306"
volumes:
- ./mysql/my.cnf:/etc/mysql/conf.d/mysql.cnf:ro
- ./mysql/sql:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 10s
retries: 10
start_period: 15s
networks:
- my-network
# phpMyAdmin(可选)
phpmyadmin:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/phpmyadmin:5.2.1
container_name: phpmyadmin
ports:
- "8899:80"
environment:
- PMA_HOST=mysql
- PMA_PORT=3306
- MYSQL_ROOT_PASSWORD=123456
depends_on:
mysql:
condition: service_healthy
networks:
- my-network
# Redis 6.2
redis:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:6.2
container_name: redis
restart: always
ports:
- "16379:6379"
networks:
- my-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
# Redis Commander(可选)
redis-admin:
image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis-commander:0.8.0
container_name: redis-admin
ports:
- "8081:8081"
environment:
- REDIS_HOSTS=local:redis:6379
- HTTP_USER=admin
- HTTP_PASSWORD=admin
depends_on:
redis:
condition: service_healthy
networks:
- my-network
networks:
my-network:
driver: bridge#!/bin/bash
CONTAINER_NAME={artifactId}
IMAGE_NAME=system/{artifactId}:1.0.0
PORT={port}
echo "容器部署开始 ${CONTAINER_NAME}"
# 停止容器
docker stop ${CONTAINER_NAME}
# 删除容器
docker rm ${CONTAINER_NAME}
# 启动容器
docker run --name ${CONTAINER_NAME} \
--network my-network \
-p ${PORT}:${PORT} \
-e SPRING_PROFILES_ACTIVE=prod \
-v $(pwd)/logs:/data/log \
-d ${IMAGE_NAME}
echo "容器部署成功 ${CONTAINER_NAME}"
# 查看日志
docker logs -f ${CONTAINER_NAME}#!/bin/bash
CONTAINER_NAME={artifactId}
echo "停止容器 ${CONTAINER_NAME}"
docker stop ${CONTAINER_NAME}
docker rm ${CONTAINER_NAME}
echo "容器已停止"server:
port: {port}
spring:
application:
name: {artifactId}
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${MYSQL_HOST:mysql}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:{database}}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: ${MYSQL_USER:root}
password: ${MYSQL_PASSWORD:123456}
hikari:
pool-name: {artifactId}-hikari
minimum-idle: 10
maximum-pool-size: 50
idle-timeout: 300000
connection-timeout: 30000
max-lifetime: 1800000
redis:
host: ${REDIS_HOST:redis}
port: ${REDIS_PORT:6379}
rabbitmq:
host: ${RABBITMQ_HOST:rabbitmq}
port: ${RABBITMQ_PORT:5672}
username: ${RABBITMQ_USER:admin}
password: ${RABBITMQ_PASSWORD:admin123}
logging:
level:
root: INFO
cn.bugstack: INFO
file:
name: /data/log/{artifactId}.log所有镜像已同步到阿里云,使用前缀 registry.cn-hangzhou.aliyuncs.com/xfg-studio/
📦 镜像来源:docker-image-pusher 添加新镜像:在 images.txt 添加镜像名,等待1分钟同步
| 原始镜像 | 阿里云加速地址 | 用途 |
|---|---|---|
| JDK/Java | ||
| openjdk:8-jre-slim | registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim | Java 8 运行环境 |
| openjdk:8-jdk | registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jdk | Java 8 开发镜像 |
| openjdk:17-jdk-slim | registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:17-jdk-slim | Java 17 运行环境 |
| openjdk:17-ea-17-jdk-slim-buster | registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:17-ea-17-jdk-slim-buster | Java 17 EA 版本 |
| 数据库 | ||
| mysql:8.0.32 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.0.32 | MySQL 8.0 |
| mysql:8.4.4 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.4.4 | MySQL 8.4 |
| postgres:14.18 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/postgres:14.18 | PostgreSQL 14 |
| pgvector/pgvector:pg17 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/pgvector:pg17 | PostgreSQL 向量库 |
| 缓存 | ||
| redis:6.2 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:6.2 | Redis 6.2 |
| redis:7.2 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:7.2 | Redis 7.2 |
| redis:7.4.13 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:7.2/7.4.13 | Redis 7.4 |
| 数据库管理 | ||
| phpmyadmin:5.2.1 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/phpmyadmin:5.2.1 | MySQL Web 管理 |
| redis-commander:0.8.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis-commander:0.8.0 | Redis Web 管理 |
| dpage/pgadmin4:9.1.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/pgadmin4:9.1.0 | PostgreSQL Web 管理 |
| 消息队列 | ||
| rabbitmq:3.12.9 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/rabbitmq:3.12.9 | RabbitMQ |
| rocketmq:5.1.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/rocketmq:5.1.0 | RocketMQ |
| kafka:3.7.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/kafka:3.7.0 | Kafka |
| kafka-eagle:3.0.2 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/kafka-eagle:3.0.2 | Kafka Eagle |
| 注册中心/配置中心 | ||
| nacos-server:v2.2.3-slim | registry.cn-hangzhou.aliyuncs.com/xfg-studio/nacos-server:v2.2.3-slim | Nacos 2.2.3 |
| nacos-server:v3.1.1 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/nacos-server:v3.1.1 | Nacos 3.1.1 |
| Web 服务器 | ||
| nginx:1.25.1 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/nginx:1.25.1 | Nginx 1.25 |
| nginx:1.28.0-alpine | registry.cn-hangzhou.aliyuncs.com/xfg-studio/nginx:1.28.0-alpine | Nginx 1.28 Alpine |
| 任务调度 | ||
| xxl-job-admin:2.4.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/xxl-job-admin:2.4.0 | XXL-Job 管理端 |
| xxl-job-aarch64:2.4.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/xxl-job-aarch64:2.4.0 | XXL-Job ARM 版本 |
| 监控 | ||
| prometheus:2.47.2 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/prometheus:2.47.2 | Prometheus |
| grafana:10.2.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/grafana:10.2.0 | Grafana |
| skywalking-oap-server:9.3.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/skywalking-oap-server:9.3.0 | SkyWalking OAP |
| skywalking-ui:9.3.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/skywalking-ui:9.3.0 | SkyWalking UI |
| 搜索引擎 | ||
| elasticsearch:7.17.14 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/elasticsearch:7.17.14 | Elasticsearch |
| kibana:7.17.14 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/kibana:7.17.14 | Kibana |
| Node | ||
| node:18-alpine | registry.cn-hangzhou.aliyuncs.com/xfg-studio/node:18-alpine | Node 18 |
| node:20-alpine | registry.cn-hangzhou.aliyuncs.com/xfg-studio/node:20-alpine | Node 20 |
| AI/工具 | ||
| ollama/ollama:0.5.10 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/ollama:0.5.10 | Ollama |
| n8nio/n8n:1.88.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/n8n:1.88.0 | N8N 工作流 |
| 其他 | ||
| alpine:3.20.1 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/alpine:3.20.1 | Alpine Linux |
| portainer:latest | registry.cn-hangzhou.aliyuncs.com/xfg-studio/portainer:latest | Docker 可视化管理 |
| jenkins:2.439 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/jenkins:2.439 | Jenkins |
| sentinel-dashboard:1.8.7 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/sentinel-dashboard:1.8.7 | Sentinel 流量控制 |
| canal-server:v1.1.6 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/canal-server:v1.1.6 | Canal |
| zookeeper:3.9.0 | registry.cn-hangzhou.aliyuncs.com/xfg-studio/zookeeper:3.9.0 | Zookeeper |
# 拉取 MySQL
docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.0.32
# 拉取 Redis
docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/redis:6.2
# 拉取 Java 17
docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:17-jdk-slimdocker exec mysql mysql -uroot -p123456 -e "ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; FLUSH PRIVILEGES;"确保所有容器在同一个网络:
networks:
- my-network修改 docker-compose.yml 中的端口映射:
ports:
- "13306:3306" # 改为非标准端口检查环境变量配置和健康检查依赖:
depends_on:
mysql:
condition: service_healthy当用户说"帮我部署 ai-mcp-gateway"时,执行:
确认项目信息
/Users/fuzhengwei/Documents/project/ddd-demo/ai-mcp-gateway8091system/ai-mcp-gateway:1.0.0执行部署
# 进入项目目录
cd /Users/fuzhengwei/Documents/project/ddd-demo/ai-mcp-gateway
# 打包
mvn clean package -Dmaven.test.skip=true
# 构建 Docker 镜像
cd ai-mcp-gateway-app
docker build -t system/ai-mcp-gateway:1.0.0 .
# 部署基础环境
cd ../docs/dev-ops
docker-compose -f docker-compose-environment-aliyun.yml up -d
# 等待 MySQL 就绪
sleep 30
# 初始化数据库
docker exec -i mysql mysql -uroot -p123456 < mysql/sql/ai_mcp_gateway_v2.sql
# 启动应用
docker-compose -f docker-compose-app.yml up -d
# 验证
docker ps | grep ai-mcp-gateway
curl http://localhost:8091/api/gateway/list© fuzhengwei, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 22 other files (scripts, references) in the repository root of fuzhengwei/xfg-ddd-skills.
Open the folder on GitHubat commit aca0123
Xfg Ddd Skills next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Xfg Ddd Skills this skillfuzhengwei/xfg-ddd-skills | 101 | — | ~13k | Automated safety check: Pass | MIT | |
| Kratos Developmentaide-family/moon | 253 | — | ~1.5k | Automated safety check: Pass | None | |
| Spring Boot Project Creatorgiuseppe-trisciuoglio/developer-kit | 357 | — | ~3.4k | Automated safety check: Notes | MIT | |
| Domain Modelingfossasia/eventyay-interpretation | 1.6k | 30 repos | ~821 | Automated safety check: Pass | Apache-2.0 | |
| Megatron-LM Container and Dependency SetupNVIDIA/Megatron-LM | 18k | — | ~2.6k | Automated safety check: Pass | Apache-2.0 | |
| Run Dozzle Dev Instanceamir20/dozzle | 15k | — | ~747 | Automated safety check: Pass | MIT |
aide-family/moon
Develops Go microservices with Kratos v2 following official design philosophy, DDD/Clean Architecture layout, Protobuf API, error/config/middleware patterns, and observability.
giuseppe-trisciuoglio/developer-kit
Creates and scaffolds a new Spring Boot project (3.x or 4.x) by downloading from Spring Initializr, generating package structure (DDD or Layered architecture), configuring JPA, SpringDoc OpenAPI…
fossasia/eventyay-interpretation
Build and sharpen a project's domain model. An agent skill from fossasia/eventyay-interpretation.
NVIDIA/Megatron-LM
Walks an agent through working inside the Megatron-LM CI container and changing dependencies with uv, so lock files resolve the same locally and in CI.
amir20/dozzle
Starts a Dozzle dev server on a port derived from the current worktree so you can test by hand in a browser, without disturbing instances started elsewhere.
brim-borium/spotify_sdk
Build and sharpen a project's domain model. An agent skill from brim-borium/spotify_sdk.
Works with
Categories
DDD 六边形架构设计与部署技能包。提供 Domain/Case/Infrastructure 层设计模式与代码模板,以及 Docker 环境部署脚本。当用户询问 DDD 架构、设计模式或需要部署项目时调用。. Xfg Ddd Skills is an agent skill from fuzhengwei/xfg-ddd-skills.
Xfg Ddd Skills fits situations like: tasks that involve Domain-driven design.
Run `npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a claude-code`. Or copy the skill folder (the fuzhengwei/xfg-ddd-skills repository) into .claude/skills/xfg-ddd-skills in your project. Claude Code loads it when a task matches its description.
Run `npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a codex`. Or copy the skill folder (the fuzhengwei/xfg-ddd-skills repository) into .agents/skills/xfg-ddd-skills in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add fuzhengwei/xfg-ddd-skills --skill xfg-ddd-skills -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/xfg-ddd-skills, .gemini/skills/xfg-ddd-skills, .github/skills/xfg-ddd-skills and .opencode/skills/xfg-ddd-skills in your project.
Going by SKILL.md and its folder, Xfg Ddd Skills needs the command-line tools its instructions call (docker, docker-compose, mvn, curl and bash) and credentials named MYSQL_ROOT_PASSWORD, HTTP_PASSWORD, MYSQL_PASSWORD and RABBITMQ_PASSWORD. Our summary lists: Docker.
SKILL.md names 1 domain. As links in the text: github.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Xfg Ddd Skills is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 13k tokens (SKILL.md is roughly 53k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 64k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Xfg Ddd Skills: Kratos Development (aide-family/moon, 253 stars), Spring Boot Project Creator (giuseppe-trisciuoglio/developer-kit, 357 stars), Domain Modeling (fossasia/eventyay-interpretation, 1.6k stars) and Megatron-LM Container and Dependency Setup (NVIDIA/Megatron-LM, 18k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
fuzhengwei (a GitHub user) maintains it in fuzhengwei/xfg-ddd-skills, which has 101 GitHub stars. The repository was last updated on May 2, 2026.
Source: fuzhengwei/xfg-ddd-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.