探索项目整体架构和 DDD 层结构
探索这个 Java DDD 项目的整体架构。我需要了解:
- 项目模块结构(各个 maven module 是什么)
- DDD 分层目录结构(domain / infrastructure / trigger / api / types 等)
- 各个领域(auth / activity / user / matching / notification) 的 domain 层现有代码情况
- 重点看 domain 层各模块有哪些 port/in(应用服务接口)、port/out(仓储接口)、model(聚合根/实体/值对象)
请列出每个模块的关键文件路径和主要内容概述。先从项目根 pom.xml 开始,看清楚 module 划分。
下面是基于根 pom.xml 与 tour-mate-platform-domain 等模块源码的架构梳理(只读扫描)。
1. Maven 模块划分(根 pom.xml)
根工程:/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/pom.xml,packaging=pom,声明 6 个子模块(第 10–17 行):
| 模块 artifactId | 目录 | 角色(与文档一致) |
|---|---|---|
| `tour-mate-platform-types' | /Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-types | 枚举、异常、常量等共享类型 |
tour-mate-platform-api | .../tour-mate-platform-api | 对外 HTTP 契约(Request/Response/DTO) |
tour-mate-platform-domain | .../tour-mate-platform-domain | DDD 领域:聚合、端口、领域服务、事件、Saga |
tour-mate-platform-infrastructure | .../tour-mate-platform-infrastructure | 仓储实现、PO、Adapter、Gateway |
tour-mate-platform-app | .../tour-mate-platform-app | Spring Boot 启动、全局配置、少量应用服务装配(如支付回调、Saga 恢复) |
tour-mate-platform-trigger | .../tour-mate-platform-trigger | Controller、定时任务、Listener(边缘适配) |
说明:domain 的 pom.xml 还依赖了 tour-mate-platform-api(注释写明「认证模块需要」),因此领域层与 API DTO 存在一定耦合,与纯 DDD 中「domain 不依赖 api」的理想形态略有出入。
2. DDD 分层在仓库里的落位
- Types
com.alisunxin.api.types— 约 5 个 Java 文件(AppException、ResponseCode、Constants等)。 - API
com.alisunxin.api.api.*、com.alisunxin.api.dto.*— Request/Response/DTO(认证、活动、匹配、通知 DTO 等)。 - Domain(核心) 根包:
com.alisunxin.api.domain,按限界上下文再分子包,典型子目录包括:port/in:应用服务接口(输入端口)port/out:仓储、外部网关、通知等(输出端口)model/aggregate、model/entityvalobj、event、service(应用服务实现或领域服务)、saga、specification、dto/query(领域内查询对象)
- Infrastructure
com.alisunxin.api.infrastructure:adapter/(repository、payment、notification 等)、dao/(po、jpa repository、converter、specification)、gateway/、service/(锁、缓存、JWT 等)。 - Trigger
com.alisunxin.api.trigger:http/(REST)、job/、listener/。 - App
com.alisunxin.api:Application.java、config/*、以及service/payment/*、service/saga/SagaRecoveryApplicationService等。 - Shared(跨域)
com.alisunxin.api.domain.shared:事件(DomainEvent、IDomainEventPublisher等)、Saga 基座(AbstractSaga、ISaga)、规格、通用值对象(如Money)。
另外还有独立领域包:chat、content、post、security(与安全/会话相关,与 auth 登录编排常一起用)。
3. 各域 Domain 现状概要
auth(.../domain/auth)
| 类别 | 路径与内容 |
|---|---|
| port/in | /Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-domain/src/main/java/com/alisunxin/api/domain/auth/port/in/IAuthApplicationService.java — 微信登录、刷新 token、登出 |
| port/out | IWechatGateway.java(微信)、IJwtService.java、ITokenExtractor.java、IUserPort.java(与用户域协作) |
| model | 本包 无 聚合根/实体;逻辑在 service/AuthApplicationService.java 中编排 |
| valobj | WechatUserInfo.java |
认证与「安全聚合」拆在 security 包(见下)。
activity(最完整,含 CQRS 与 Saga)
| 类别 | 关键路径与概述 |
|---|---|
| port/in | IActivityApplicationService.java — 创建/发布/取消/报名/退出/开始/完成等活动写操作;IActivityQueryApplicationService.java — 查询;IActivityMemberApplicationService.java — 成员相关命令;IPaymentCallbackApplicationService.java、IRefundRetryApplicationService.java — 支付/退款编排入口(接口在 domain,部分实现在 app/infrastructure) |
| port/out | IActivityAggregateRepository.java、IActivityMemberRepository.java;IPaymentPort.java、IUserCreditPort.java;IAlertPort.java;通知:IActivityNotificationPort.java(领域事件/聚合驱动,Saga 使用)与 ActivityNotificationPort.java(另一套按 ID/Location 等参数的接口,内容上属于同类能力的另一形态) |
| model | model/aggregate/ActivityAggregate.java;model/entity/ActivityMemberEntity.java |
| 其它 | valobj/(含 ActivityId、Location、支付/退款/信用等);event/(创建、取消、开始、完成、成员进退、退款成功等);saga/(报名、取消、完成、退出、PartialRefundSaga 等);service/(ActivityApplicationService、ActivityQueryApplicationService、ActivityMemberApplicationService 及多项事务服务) |
user
| 类别 | 关键路径与概述 |
|---|---|
| port/in | port/in/package-info.java 标明 IUserApplicationService 等待添加,当前 无 正式应用服务接口 |
| port/out | IUserRepository.java(聚合持久化);IUserInterestRepository.java;UserNotificationPort.java(欢迎邮件、验证码、安全通知等) |
| model | UserAggregate.java(含 UserEntity、兴趣列表与领域事件收集);entity/UserEntity.java、UserInterestEntity.java |
| 其它 | valobj/UserId.java、Email.java、PhoneNumber.java;service/(UserRegistrationService、UserAuthenticationService);specification/UserSpecifications.java;event/UserRegisteredEvent.java |
matching
| 类别 | 关键路径与概述 |
|---|---|
| port/in | port/in/package-info.java 标明 IMatchingApplicationService 等待添加,当前 无 正式应用服务接口 |
| port/out | IMatchingAggregateRepository.java、IMatchResultRepository.java、IUserPreferenceRepository.java;MatchingAlgorithmPort.java(内嵌 MatchResult 嵌套类,与聚合里的结果列表命名需留意区分) |
| model | MatchingAggregate.java(MatchRequestId、MatchingCriteria、状态、结果列表、领域事件);entity/MatchRequestEntity.java、MatchResultEntity.java、UserPreferenceEntity.java |
| 其它 | service/MatchingService.java、RecommendationService.java;specification/MatchingSpecifications.java;dto/query/* |
notification(独立领域包)
不存在目录:
.../domain/notification(0 个文件)。能力分布
:
- 活动侧:
activity/port/out/IActivityNotificationPort.java(及ActivityNotificationPort.java)— 创建/取消/开始/完成/成员进退等通知。 - 用户侧:
user/port/out/UserNotificationPort.java— 邮件/短信/安全类通知。 - 接入层占位:
.../tour-mate-platform-trigger/.../NotificationController.java—/api/v1/notifications,注释里写明服务未注入,偏脚手架。
- 活动侧:
基础设施:例如
.../infrastructure/adapter/notification/AlertAdapter.java、dao侧有NotificationJpaRepository、NotificationPoSpecs等,支撑通知持久化/告警,但领域层没有单独的「Notification 聚合」包。
与「认证」强相关的 security(建议一并理解)
| 类别 | 关键路径与概述 |
|---|---|
| port/in | package-info — 应用服务接口待添加 |
| port/out | ISecurityAggregateRepository.java、IUserSessionRepository.java、IRoleRepository.java、IUserRoleRepository.java、ITokenValidationPort.java |
| model | SecurityAggregate.java;实体 UserSessionEntity、RoleEntity、UserRoleEntity |
| service | AuthenticationService、AuthorizationService、EncryptionService;事件 UserLoginEvent、UserLogoutEvent |
4. 其它 Domain 子包(便于对照仓库全貌)
chat:port/in待扩展;port/out含IChatMemberRepository、IMessageRepository、MessageDeliveryPort;含ChatMemberService、事件MessageSentEvent等。content/post:内容聚合、审核端口、帖子实体等(与活动/社交内容相关)。shared:event、saga(含ISagaRecoveryApplicationService)、specification、valobj/BaseId、Money等。
5. 小结
- 模块:根 POM 固定为 6 个 Maven 子模块(types → api → domain ← infrastructure;app 组装;trigger 暴露 HTTP/Job)。
- DDD 目录:领域代码集中在
com.alisunxin.api.domain.{context},按port/in|out、model、service、event、saga等拆分;infrastructure 用adapter+dao实现端口。 - 你关心的五块:activity 最完整(含 in/out/model 与 Saga);auth 有明确
IAuthApplicationService但无本包聚合;user / matching 模型与 out 端口较全,in 端口在 package-info 中仍标为待办;notification 没有独立domain/notification包,由 activity/user 的 Notification Port + infrastructure adapter(及 Trigger 占位接口)承担。
若你需要,我可以再按「从 Controller 到某个用例」画一条具体调用链(例如微信登录或活动报名)只做只读追溯。
查看现有数据库表和 Cursor 规则
请查找以下内容: 1. 搜索项目中所有 *.sql 文件(建表语句、migration 等) 2. 读取 .cursor/rules/ddd-core.mdc 文件 3. 读取 .cursor/rules/ports-naming.mdc 文件 4. 读取 .cursor/rules/saga-event.mdc 文件 5. 读取 CLAUDE.md 文件 6. 查看 docs/ 目录下有没有数据库设计文档或 ER 图 7. 搜索项目中的 JPA Entity 类(搜索 @Entity 注解),列出所有已有的数据库实体 请把这些信息都整理出来。
1. 项目中所有 *.sql 文件(共 7 个)
| 绝对路径 |
|---|
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/dev-ops/docker/mysql/sql/init.sql |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/dev-ops/docker-simple/mysql/sql/init.sql |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/migrations/000_full_schema_snapshot.sql |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/migrations/001_create_users_table.sql |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/migrations/002_wechat_login_migration.sql |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/migrations/003_domain_event_record_table.sql |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/migrations/004_saga_state_table.sql |
说明:docs/migrations/ 下为增量迁移与全量快照;两处 init.sql 对应 Docker / docker-simple 的 MySQL 初始化。
2. .cursor/rules/ddd-core.mdc 要点
- Front matter:针对
**/*.java,描述为 DDD 六边形核心分层与编码规范。 - 分层:Domain(充血模型、Port)、Infrastructure(Repository/PO/Adapter)、App(编排与组装)、API(契约)、Trigger(Controller/Job/Listener)、Types(枚举/异常等)。
- 依赖:允许 Trigger→Domain/API、Domain→Types、Infrastructure→Domain、App→各层;禁止 Trigger 直接依赖 Infrastructure、Domain 依赖 Infrastructure 等。
- 转换链:Request→Command→Entity→PO→DB;逆向 Response←DTO←Entity←PO。
- 流程:先 Domain,再 Infra、App、API、Trigger。
- 编码:Lombok、
AppException、Response<T>、公共方法 JavaDoc。
3. .cursor/rules/ports-naming.mdc 要点
- Input Port:
IXxxApplicationService,domain/xxx/port/in/,App 实现、Trigger 调用。 - Output Port:仓储
IXxxRepository、外部IXxxPort,domain/xxx/port/out/,Infra 实现。 - Adapter:仓储实现类名
XxxRepository(无 Adapter 后缀),infrastructure/adapter/repository/;外部XxxAdapter;事件DomainEventPublisherAdapter。 - API:
XxxRequest/XxxResponse。 - 原则:Port 用领域对象;Adapter 只做技术实现、异常转
AppException、关键操作幂等。
4. .cursor/rules/saga-event.mdc 要点
- 领域事件:Domain 中
DomainEvent基类 +XxxEvent(过去时);聚合根收集事件;ApplicationService 通过IDomainEventPublisher发布;Infrastructure 里@Async+@TransactionalEventListener(AFTER_COMMIT)监听。 - Saga:
ISaga<C>、SagaStatus;示例ActivityCancellationSaga:持久化状态、分步执行、失败补偿逆序、步骤幂等。 - 事务:聚合内同一事务;跨聚合用事件或 Saga;监听器 AFTER_COMMIT + 异步。
5. CLAUDE.md 要点
与根目录项目说明一致:Java 17、Spring Boot 3.4.3、MySQL、MyBatis + Spring Data JPA、Redis;六层模块名(trigger/app/domain/infrastructure/api/types);调用链 HTTP→Controller→ApplicationService→聚合→Repository→DB;依赖倒置、统一异常与响应、充血模型、事件驱动、Saga;命名速查表;并指向上述三条 .mdc 规则。
6. docs/ 下数据库设计 / ER 图
未发现 专用 ER 图文件:全仓库未匹配到
*.puml、*.mmd、*.drawio、*.dbml、*.erd等常见 ER 载体。与“数据库设计 / 表结构”相关的 Markdown
(多为业务文档章节,非统一 ER 文档)例如:
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/需求文档/微信登录/uni-app 前端对接文档/微信登录实现总结.md(含「数据库设计」)/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/需求文档/微信登录/后端对接文档/微信登录实现总结-后端.md/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/需求文档/微信登录/后端对接文档/微信登录快速开始.md(「数据库表结构」)/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/需求文档/微信登录/uni-app 前端对接文档/微信登录后端接入要求.md/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/活动退款场景/PARTIAL_REFUND_IMPLEMENTATION.md(标注「数据库设计(待创建)」)
结构性参考:
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/README.md、/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/开发工作流指南.md、/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/docs/项目结构说明.md将docs/migrations/000_full_schema_snapshot.sql作为全量建表快照与维护约定。
结论:没有集中的 ER 图文档;实际表结构以 docs/migrations/(尤其 000_full_schema_snapshot.sql)和部分需求文档章节为主。
7. 带 @Entity 的 JPA 实体(Infrastructure PO,共 13 个)
均在 tour-mate-platform-infrastructure 的 com.alisunxin.api.infrastructure.dao.po 包下:
| 类文件绝对路径 |
|---|
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/ActivityMemberPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/ActivityPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/ChatPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/DomainEventRecordPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/MatchRequestPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/MatchResultPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/NotificationPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/PostPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/RolePO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/SagaStatePO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/UserPO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/UserRolePO.java |
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/dao/po/UserSessionPO.java |
如需某份 .sql 的表清单对照上述 PO,可在 Agent 模式下让我逐文件拆解 CREATE TABLE。
分析 Activity 模块已实现的 DDD 完整链路
分析 Activity 模块作为 "已实现" 的参考模板。我需要了解其完整 DDD 调用链,以便后续其他模块(User / Matching / Notification)参照实现。请检查:
- Domain 层: -
tour-mate-platform-domain下activity包内的所有文件 - 聚合根ActivityAggregate- 端口定义 port/in(应用服务接口)和 port/out(仓储接口) - 值对象、枚举 - Infrastructure 层: -
tour-mate-platform-infrastructure下 activity 相关的 Repository 实现 - JPA Entity 定义 - Entity ↔ Domain 转换器 - API / DTO 层: -
tour-mate-platform-api或tour-mate-platform-types下的 request/response DTO - Converter 转换器
请给出 Activity 模块的完整文件清单和关键代码结构,作为后续开发的参考模板。
下面是对当前仓库里 Activity 模块 的梳理结果(只读检索结论),可作为 User / Matching / Notification 对齐实现的参照。注意:本项目里多数 Activity「应用服务」实现放在 tour-mate-platform-domain 的 activity/service 包并标注 @Service,与文档里「App 层独占 ApplicationService」的叙述不一致;只有少数接口(如退款重试、支付回调)在 tour-mate-platform-app 实现。
1. 完整调用链(HTTP → 持久化 / 出站)
典型链路与 ActivityController 注释一致:
HTTP → Trigger(Controller)→ Domain port/in(应用服务接口)→ Domain 应用服务实现(@Service,位于 domain 模块)→ ActivityAggregate / Saga / 领域服务 → Domain port/out(仓储与网关)→ Infrastructure(Repository / Adapter)→ DB / 外部系统
触发层示例:
ActivityController.javaLines 44-57
* 完整调用链:
* HTTP请求 → ActivityController (Trigger)
* ↓
* IActivityApplicationService (Domain接口)
* ↓
* ActivityApplicationService (Domain实现) - 事务管理 / 业务编排
* ↓
* ActivityAggregate (Domain) - 业务逻辑
* ↓
* IActivityAggregateRepository (Domain接口)
* ↓
* ActivityAggregateRepository (Infrastructure) - 数据持久化
* ↓
* DatabaseCQRS:写操作走 IActivityApplicationService,读操作走 IActivityQueryApplicationService,成员相关另有 IActivityMemberApplicationService。
事件 / 通知:事务提交后由 Infrastructure 的 ActivityEventListener 监听领域事件,再调用 IActivityNotificationPort(由 ActivityNotificationAdapter 实现)。
混合 App 层:RefundRetryApplicationService(/tour-mate-platform-app/...)实现 IRefundRetryApplicationService,注释写明属于 App 层编排。
2. Domain 层:tour-mate-platform-domain/.../domain/activity(共 56 个 .java)
根路径:/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-domain/src/main/java/com/alisunxin/api/domain/activity/
2.1 聚合根与实体
路径(相对 domain/activity) | 说明 |
|---|---|
model/aggregate/ActivityAggregate.java | 聚合根;内含 ActivityStatus、CostType 枚举 |
model/entity/ActivityMemberEntity.java | 成员实体 |
model/entity/package-info.java | 包说明 |
2.2 Port In(应用服务接口,port/in)
| 文件 | 职责概要 |
|---|---|
IActivityApplicationService.java | 命令侧:创建/发布/取消/开始/完成/报名/退款申请等 |
IActivityQueryApplicationService.java | 查询侧 |
IActivityMemberApplicationService.java | 成员侧命令 |
IPaymentCallbackApplicationService.java | 支付回调入口契约 |
IRefundRetryApplicationService.java | 退款重试契约(实现在 app 模块) |
2.3 Port Out(仓储与外部端口,port/out)
| 文件 | 说明 |
|---|---|
IActivityAggregateRepository.java | 活动聚合仓储(含 Specification、search、场景查询等) |
IActivityMemberRepository.java | 成员仓储 |
IPaymentPort.java | 支付出站端口 |
IUserCreditPort.java | 用户信用出站端口 |
IAlertPort.java | 告警出站端口 |
IActivityNotificationPort.java | 事件驱动通知(方法参数多为领域事件) |
ActivityNotificationPort.java | 另一套通知抽象(参数多为 ActivityId/UserId/Location 等);与 IActivityNotificationPort 并存,命名风格不统一,后续模块建议统一为一种 |
package-info.java | 包说明 |
2.4 应用服务 / 事务服务实现(均在 Domain 模块,service/)
| 文件 | 角色 |
|---|---|
ActivityApplicationService.java | IActivityApplicationService 实现,编排 Saga、仓储、事件发布 |
ActivityQueryApplicationService.java | 查询应用服务 |
ActivityMemberApplicationService.java | 成员应用服务 |
ActivityTransactionService.java | 事务相关领域编排 |
ActivityRegistrationTransactionService.java | 报名事务 |
ActivityQuitTransactionService.java | 退出事务 |
RefundApplicationTransactionService.java | 退款申请事务 |
package-info.java | 包说明 |
2.5 Saga / Command
| 文件 |
|---|
saga/ActivityCancellationCommand.java, ActivityCancellationSaga.java |
saga/ActivityCompletionCommand.java, ActivityCompletionSaga.java |
saga/ActivityQuitCommand.java, ActivityQuitSaga.java |
saga/ActivityRegistrationCommand.java, ActivityRegistrationSaga.java |
saga/PartialRefundCommand.java, PartialRefundSaga.java |
2.6 领域事件(event/)
| 文件 |
|---|
ActivityCreatedEvent.java, ActivityCancelledEvent.java, ActivityStartedEvent.java, ActivityCompletedEvent.java |
MemberJoinedEvent.java, MemberQuitEvent.java |
RefundSuccessEvent.java |
2.7 规格与查询 DTO
| 文件 |
|---|
specification/ActivitySpecifications.java |
dto/query/ActivitySearchCriteria.java, dto/query/ActivitySearchResult.java |
2.8 值对象与枚举(含 payment/credit)
| 路径 | 类型 |
|---|---|
valobj/ActivityId.java, Location.java, RegistrationResult.java | 值对象 |
valobj/payment/OrderRequest.java, OrderResult.java, OrderStatus enum, RefundRecord.java, RefundReason.java, RefundResult.java, RefundStatus enum | 订单/退款相关 |
valobj/credit/CreditAddReason.java, CreditDeductionReason.java | 信用原因枚举 |
聚合内枚举(非独立文件):ActivityAggregate.ActivityStatus、ActivityAggregate.CostType。
3. Infrastructure 层(Activity 相关)
根:/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-infrastructure/src/main/java/com/alisunxin/api/infrastructure/
| 绝对路径 | 职责 |
|---|---|
.../adapter/repository/ActivityAggregateRepository.java | 实现 IActivityAggregateRepository,ActivityConverter + ActivityJpaRepository |
.../adapter/repository/ActivityMemberRepository.java | 实现 IActivityMemberRepository,Entity ↔ PO 转换写在仓储类内部(entityToPO / poToEntity) |
.../dao/po/ActivityPO.java | JPA 实体 / 表 activities |
.../dao/po/ActivityMemberPO.java | 成员 PO |
.../dao/repository/ActivityJpaRepository.java | Spring Data JPA |
.../dao/repository/ActivityMemberJpaRepository.java | 成员 JPA |
.../dao/converter/ActivityConverter.java | Aggregate ↔ ActivityPO |
.../dao/specification/ActivityPoSpecs.java | PO 层 JPA Specification |
.../adapter/notification/ActivityNotificationAdapter.java | 实现 IActivityNotificationPort |
.../adapter/event/listener/ActivityEventListener.java | @TransactionalEventListener + @Async,对接通知端口 |
支付相关(Activity 流程会用到):.../adapter/payment/PaymentAdapter.java、EmptyPaymentAdapter.java。
4. API / DTO / Converter(及 Trigger)
4.1 tour-mate-platform-api
根:/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-api/src/main/java/com/alisunxin/api/
Request(api/request/)
CreateActivityRequest.java,PublishActivityRequest.java,CancelActivityRequest.javaJoinActivityRequest.java,RegisterActivityRequest.javaStartActivityRequest.java,CompleteActivityRequest.java
Response(api/response/)
ActivityResponse.java,ActivityDetailResponse.java,ActivityMemberResponse.java
DTO
api/dto/activity/ActivityDTO.javadto/activity/ActivitySearchRequest.java,dto/activity/ActivitySearchResponse.java(与 Domain 的ActivitySearchCriteria/ActivitySearchResult在 Controller 里组合使用)
统一响应外壳:api/response/Response.java(Controller 中使用)。
4.2 Trigger 层转换器
| 绝对路径 |
|---|
/Users/sunxin/IdeaProjects/skeeter/tour-mate-platform/tour-mate-platform-trigger/src/main/java/com/alisunxin/api/trigger/converter/ActivityResponseConverter.java |
职责:ActivityAggregate → ActivityResponse(Trigger 层防腐)。
4.3 tour-mate-platform-types(与 Activity 直接相关)
| 绝对路径 |
|---|
.../types/exception/ActivityQueryException.java |
.../types/exception/ActivityRepositoryException.java |
5. 模板化时可对齐的「关键结构」要点
- 分层契约:Trigger 只依赖 Domain
port/in+ API DTO;仓储与外部系统依赖 Domainport/out,实现在 Infrastructure。 - 两套持久化映射:活动聚合用独立
ActivityConverter;成员仓储把 Entity ↔ PO 放在ActivityMemberRepository内(新模块可二选一统一风格)。 - 枚举位置:核心业务状态可在聚合根内(如
ActivityStatus);支付子域可用独立 enum 文件(如OrderStatus)。 - CQRS:命令 / 查询拆接口;Controller 注释已写明分工。
- 与本仓库文档的差异:Activity 的
ActivityApplicationService等在 domain 模块,复制模板时不要强行把所有应用服务塞进 app,除非你打算重构现有约定。 - 通知端口:存在
ActivityNotificationPort与IActivityNotificationPort两套命名;当前适配器实现的是IActivityNotificationPort。
若你希望后续模块严格对齐「应用服务只在 App 模块」,需要先约定是否对 Activity 做一次物理迁移;若以现状为准,新模块可直接沿用「domain 模块内的 @Service 应用服务 + trigger 注入接口」这一套。
小结:已列出 Domain 下 activity 共 56 个 Java 文件的分类清单、Infrastructure/API/Types/Trigger 相关路径,并说明了 HTTP→仓储→事件的调用链及与本项目文档不一致的应用服务放置方式(便于你拷贝模板时少走弯路)。
看了你的项目结构文档,你的设计意图很清晰。我来回答你的架构问题。
应用服务放 Domain 层 vs App 层
你现在的做法是完全合理的,而且对你这个项目来说是更好的选择。原因如下:
DDD 社区对此有两种主流实践,不是非此即彼:
方案 A:应用服务放 App 层(Vaughn Vernon 风格)
- App 层负责事务协调、用例编排
- Domain 层只有聚合根、实体、领域服务、Port 接口
- 优点:Domain 模块极其纯粹,零 Spring 依赖
- 代价:App 层会变得很重,且需要与 Domain 层频繁跨模块交互
方案 B:应用服务放 Domain 层(你的做法,也是很多实际项目的选择)
- Domain 的
service/下放XxxApplicationService,实现port/in中定义的接口 - App 层只负责组装(启动类、配置、跨域编排如 Saga 恢复)
- 优点:一个领域包内自包含——模型、端口、实现、事件、Saga 都在一起,改一个功能不用跨模块跳转
- 代价:Domain 模块会依赖 Spring
@Service/@Transactional注解
从你的代码来看,方案 B 更适合你:
- 你的 Activity 模块已经稳定运行,
ActivityApplicationService在domain/activity/service/下,与聚合根、Saga、事件放在一起,改动时上下文完整 - App 层
service/只放了真正的"跨域编排"——payment/和saga/SagaRecoveryApplicationService,这恰好是该层该做的事 - 你的
CLAUDE.md和ddd-core.mdc虽然文字上写了"App 层放 ApplicationService",但实际代码约定是方案 B,代码即文档,以代码为准
结论:新模块(User/Matching/Notification/Security)的应用服务全部放在 Domain 层的 service/ 包下,与 Activity 模块保持一致。计划不需要修改。