Skip to content

快速开始 ​

DDK 尚未发布到 Maven 中央仓库,需要先在本地构建安装。之后有三条路:用 archetype 生成新服务、运行示例看一个完整用例、或者在已有项目里按需引入 starter。

DDK module map

一条命令上手 ​

脚本会检查 JDK 21+ 与 Maven,把 DDK 克隆到 ~/.ddk/src 并安装到本地仓库,再用 archetype 生成项目:

bash
curl -fsSL https://raw.githubusercontent.com/poppycoderr/domain-driven-kit/main/scripts/ddk.sh | bash -s -- new order-service --group com.acme
cd order-service && mvn verify
选项 / 环境变量默认值说明
--groupcom.example生成项目的 groupId
--packagegroupId + 去掉连字符的 artifactId根包名
--layers43 或 4,选择三层 / 四层骨架
DDK_REFmain构建的分支或 tag,例如 v0.1.0
DDK_HOME~/.ddk源码检出目录

只安装不生成项目:ddk.sh install。下面是脚本背后的手动步骤。

一、本地构建 ​

bash
git clone https://github.com/poppycoderr/domain-driven-kit.git
cd domain-driven-kit
mvn install

环境要求:JDK 21、Maven 3.9+。构建会把 com.ddk:*:0.3.0-SNAPSHOT 装到本地仓库。只想快速安装、不关心测试时可以加 -DskipTests;提交代码前请完整跑一遍,CI 使用的是 mvn install -Parchetype-it。

二、生成一个新服务 ​

bash
mvn archetype:generate \
  -DarchetypeGroupId=com.ddk \
  -DarchetypeArtifactId=ddk-layer4-archetype \
  -DarchetypeVersion=0.3.0-SNAPSHOT \
  -DgroupId=com.acme \
  -DartifactId=order-service \
  -Dpackage=com.acme.order \
  -DinteractiveMode=false

cd order-service
mvn verify
mvn spring-boot:run

业务简单的服务可以换成 ddk-layer3-archetype,两者的取舍见四层架构 / 三层架构。

生成的项目:

text
order-service
├── pom.xml                      spring-boot-starter-parent + ddk-dependencies BOM
├── AGENTS.md / CLAUDE.md        写给 AI 编码代理的约定与完成标准
├── .claude/skills               Claude Code Skills:新增聚合、用例、领域事件
└── src
    ├── main/java/com/acme/order
    │   ├── Application
    │   ├── adapter/controller
    │   ├── application/{command,query,response,service,handler}
    │   ├── domain/{model,event,acl,service,error}
    │   └── infrastructure/{acl/impl,converter,orm/po,orm/mapper}
    ├── main/resources/application.yml       内存 H2,开箱即可启动
    ├── main/resources/db/migration          Flyway 迁移脚本,自带一个基线 V1__baseline.sql
    └── test/java/com/acme/order
        ├── ApplicationTest                  上下文启动
        └── ArchitectureTest                 分层规则,违反即构建失败,报告写入 target/archguard

表结构由 Flyway 管理:每次变化在 db/migration 下新增一个 V<版本号>__<说明>.sql,启动时自动执行,已执行过的脚本不再修改。接入 MySQL 时除了驱动还要引入 flyway-mysql。(v0.3.0 及更早版本生成的项目没有这个目录。)

每个包里的 package-info.java 写明了它放什么。生成的项目不含示例代码,没有需要删除的东西。用 Claude Code、Codex 在生成的项目里开发,见用 AI 编码代理开发。

三、运行示例 ​

ddk-examples/ddk-example-user 是一个完整的四层用例:注册、查询、分页、修改、禁用 / 启用、删除,内存 H2 带种子数据。

bash
mvn -pl ddk-examples/ddk-example-user spring-boot:run
bash
curl -s -X POST localhost:8080/users -H 'Content-Type: application/json' \
  -d '{"username":"dave01","password":"password123","gender":1,"phoneNumber":"13900139001"}'
curl -s localhost:8080/users/1001

一个请求如何穿过四层:

text
POST /users
  UserController.register              adapter         @Valid RegisterUserRequest → RegisterUserCommand
    UserService.register               application     @Transactional:检查用户名占用,编排领域对象
      User.register                    domain          守卫不变量,登记 UserRegisteredEvent
      UserRepository.create            domain 端口
        UserRepositoryImpl             infrastructure  User → UserPO → t_user,发布领域事件
    UserResponse.from(user)            application     手机号脱敏
  UserEventHandler.on(...)                             事务提交后执行

示例 README 里有完整的冒烟命令,以及「每个类演示了哪个取舍」的对照表。

四、在已有项目中引入 ​

先 import ddk-dependencies BOM,之后引依赖不用再写版本号:

xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.ddk</groupId>
            <artifactId>ddk-dependencies</artifactId>
            <version>0.3.0-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.ddk</groupId>
        <artifactId>ddk-web-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.ddk</groupId>
        <artifactId>ddk-mybatis-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.ddk</groupId>
        <artifactId>ddk-event-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.ddk</groupId>
        <artifactId>ddk-archguard-starter</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

注意引的是 ddk-mybatis-starter 而不是 ddk-mybatis:通用仓储依赖的 MapperProvider 由前者的自动配置注册。

写一个用例需要落下这些类,以示例为参照:

层类示例
domain聚合根、标识、值对象、事件、仓储端口User、UserId、PhoneNumber、UserRegisteredEvent、UserRepository
infrastructurePO、Mapper、两个方向的转换器、仓储实现UserPO、UserMapper、UserPoConverter、UserEntityConverter、UserRepositoryImpl
application命令、查询、响应、应用服务RegisterUserCommand、UserPageQuery、UserResponse、UserService
adapter请求对象、控制器RegisterUserRequest、UserController

Entity ↔ PO 的两个转换器都必须注册,漏掉任何一个,仓储在第一次调用时就会抛 MissingMapperException,并在消息里给出转换器模板。

五、配置示例 ​

yaml
spring:
  application:
    name: order-service
  datasource:
    url: jdbc:mysql://localhost:3306/orders
    username: app
    password: secret

ddk:
  mybatis:
    db-type: mysql          # 分页方言
    max-page-size: 500
    worker-id: 1            # 雪花 ID 机器号,多实例部署必须区分
  web:
    cors:
      enabled: true
      allowed-origins: [ "https://admin.acme.com" ]

所有 starter 的配置都在 ddk.* 前缀下,并生成了配置元数据,IDE 里有补全。各项说明见 starter 文档。

六、上手前值得知道 ​

行为原因
JSON 里的 Long 是字符串雪花 ID 超出 JavaScript 安全整数范围,数字形式会在浏览器里静默丢精度。可用 ddk.web.write-long-as-string=false 关闭
领域不变量违反返回 400值对象、聚合抛带领域错误码的 BusinessException,全局异常处理转成 400
pageSize 默认上限 200(MyBatis 插件层 500)防止单次查询拉取过多数据,特殊接口在查询对象里覆盖 setter
PageQuery.addSort() 没有字段白名单对外开放排序参数时,自己做字段映射
跨域默认关闭库不替使用方开跨域,按需配置 ddk.web.cors.*

相关文档 ​

文章以 CC BY-NC-SA 4.0 授权 · 代码片段以 MIT 授权