Files
saas-mbr/abacus.springboot.example/.project.agents/docs/context/ARCHITECTURE.md
T

179 lines
7.8 KiB
Markdown
Raw Normal View History

# abacus.springboot.example — 架构文档(ARCHITECTURE
> 模块、依赖、契约、目录布局的**唯一权威**(本仓库视角)。新增/重命名/移动模块或调整依赖方向,必须先改本文,再改代码(同一个 commit)。
> 上游:`PRD.md`(行为)。前后端共享约束见工作区 `docs/``../../../../docs/coding-standards.md` §5 后端规范、§6 接口契约),本文不复制其正文。
## 0. 阅读指引
本文描述后端模板的模块划分与依赖方向;§2 模块清单与 §6 目录一一对应,§3.2 是跨模块接口契约。新会话先读 §2 + §6 定位任务归属,再动手。
## 1. 领域模型(Domain Model
### 1.1 实体
模板自带示例纵切面(稽查 JcBill),供复制改写:
| 实体 | 字段 | 关系 | 持久化? |
|---|---|---|---|
| jc_bill(稽查主单) | id(@Id)/version(@Version)/status/… | 1:N 明细 | 是 |
| jc_bill_item / jc_bill_photo / jc_bill_hg / jc_bill_hg_pay / jc_source_item / jc_bill_in_item / jc_bill_source_item | id/主单关联字段 | N:1 主单 | 是 |
字段细节见 `dao/*.java``sql/upgrade.xml`(建表 DDL)。
### 1.2 派生概念(非持久化)
- `api/view/*`:请求/响应 DTOApiReq*/ApiResp*),编排层与 Controller 之间传递。
- `@Transient` 字段:实体上的非持久化附加信息(如 `recsource`)。
### 1.3 不变量(任何模块都必须维护)
- I1. 业务主键一律由 `DaoIdGenerator` 生成(prefix+yyyyMMdd+serialLength),禁止手拼/UUID。
- I2. 原生 SQL 全量 `?` 参数化,禁止字符串拼接。
- I3. 分层依赖单向:api/controller → esb/wsi → {pi/impl, repository} → dao;禁止反向依赖。
- I4. Controller 直接 return 业务对象,禁止手拼统一响应体。
## 2. 模块清单
按依赖层级从低到高排列。
### Layer 0 — dao(实体层)
```
## 模块名:dao
- 职责:JPA 实体(表映射、状态常量、@Version 乐观锁)
- 不负责:查询逻辑、业务规则
- 输入:无(被 repository/impl 引用)
- 输出:实体类型
- 关键类型/接口:@Entity 类(如 JcBill
- 持有状态:无(纯数据)
```
### Layer 0 — config(基础设施配置)
```
## 模块名:config
- 职责:@ConfigurationDaoIdGenerator、AbacusConfigNote 默认值)+ 配置 key 常量
- 不负责:业务规则
- 输入:application.yml / Nacos 配置
- 输出:基础设施 Bean
- 持有状态:无
```
### Layer 1 — repository / pi+impl(数据访问)
```
## 模块名:repositorySpring Data JPA
- 职责:标准 CRUD 与派生查询(findByXxx
- 不负责:复杂查询(走 pi/impl)
- 输出:实体查询结果
## 模块名:pi + impl(原生 SQL 访问)
- 职责:复杂查询/批量写(pi 定义接口,impl 实现,SQL 参数化)
- 不负责:业务编排
- 输出:DTO/实体结果
```
### Layer 2 — esb / wsi(服务编排与接口)
```
## 模块名:esb + wsi
- 职责:业务用例编排(esb/*BizService@Service)、对外服务接口(wsi/*ServiceIF
- 不负责:直接 SQL、Controller 层参数解析
- 输入:Controller 传入的 DTO/参数
- 输出:编排结果(DTO/实体)
- 持有状态:事务边界(@Transactional 按需)
```
### Layer 3 — api / controller(接口层)
```
## 模块名:api + controller
- 职责:对外接口(api/,springdoc 扫描)与前端/内部接口(controller/abacus.controllerPackages 扫描)
- 不负责:业务编排与 SQL
- 输入:HTTP 请求(@RequestParam/@RequestBody
- 输出:业务对象(由 ResultResponseBodyWrapper 包装)
- 持有状态:无
```
## 3. 依赖图(DAG
```mermaid
graph TD
api_controller[api / controller] --> esb_wsi[esb / wsi]
esb_wsi --> pi_impl[pi / impl]
esb_wsi --> repository[repository]
pi_impl --> dao[dao]
repository --> dao
esb_wsi --> dao
config -.注入.-> esb_wsi
config -.注入.-> pi_impl
```
### 3.1 依赖方向规则
- 高层依赖低层,单向;**禁止** dao 依赖 repository、esb 依赖 controller 等反向依赖。
- 跨层调用走接口(wsi ServiceIF / pi AccessIF),不 reach into 实现。
### 3.2 跨模块接口契约(写代码时必须遵守的签名)
```
// module: controller
// @RequestMapping(value, method) -> 业务对象(throws Exception // 直接 returnI4
// module: esb/wsi
// XxxServiceIF.method(dto...) throws Exception // 编排用例,事务边界
// module: pi/impl
// XxxAccessIF.method(params...) -> List<DTO> // 原生 SQLI2 参数化
// module: repository
// XxxRepository extends JpaRepository<Entity, String>, JpaSpecificationExecutor<Entity>
// module: config
// @Bean DaoIdGeneratorprefix/useDateFormat/yyyyMMdd/serialLength // I1
```
## 4. 持久化与边界
- 数据源:Druid 连接池 + JPA;多数据源由 Nacos `abacus-database.yml` 提供(enableMultiSource / multidb0~9 / defaultDB / readDB / dynamicRelation)。
- 外部边界:Nacos(注册+配置)、Kafka(消息)、XXL-JOB(调度)、Feign(服务间调用)、springdoc(接口文档)、Actuator(监控)。
## 5. 测试边界
- 无自动化单测(PRD 决策);接口人工冒烟。
- **必须真机验证**:多数据源路由、Kafka 消费、XXL-JOB 调度、Nacos 配置拉取、真实数据库迁移——mock/模拟器不算数。
## 6. 目录结构(与 §2 模块清单一一对应)
```
src/main/java/abacus/springboot/<应用名>/
├── Application.java # 入口(注册 ResultResponseBodyWrapper
├── api/ # 对外 Controllerspringdoc 扫描);api/view/ 放 DTO
├── controller/ # 前端/内部 Controllerabacus.controllerPackages 扫描)
├── dao/ # JPA 实体(abacus.entitypackages 扫描)
├── esb/ # Service 编排层(@Service
├── wsi/ # 服务接口 *ServiceIF
├── pi/ # 数据访问接口 *AccessIF
├── impl/ # 数据访问实现(原生 SQL)
├── repository/ # Spring Data JPA Repository
├── config/ # @Configuration + 配置常量
├── util/ vo/ # 既有兼容(可引不可增)
src/main/resources/
├── config/{dev,test,prod}/ # 三套同构配置
├── sql/{table,data}/ + upgrade.xml # 建表双份/初始化/版本化升级
├── html/vue/<应用名>/ # 前端构建产物(打包入 *-bin.zip)
└── doc/升级日志.md # 功能更新记录
```
## 7. 自检(架构健康度三问)
1. 出 bug 了,能否 30 秒内指出是哪个包(controller/esb/impl/repository)的责任?
2. 换数据库/换 JPA 实现,改动能否控制在 impl/repository + 配置内?
3. 加新业务接口,能否立刻说出它落在 api 还是 controller、esb 是否要新增 BizService
## 8. 待办与已知技术负债
- `springdoc-openapi-maven-plugin``apiDocsUrl` 硬编码 `http://localhost:8080/v3/api-docs`,与应用实际端口(9060)不一致,生成 openapi.json 时需手工修正。
- `prod/application.yml` 引用 `abacus.springboot.example.springdoc` 扫描路径但该包不存在(模板未创建 springdoc 包)——新系统以实际包为准。
## 9. 文档变更协议
- 加/删模块或改依赖方向 → 改本文 §2 + §3,同一 commit。
- 改对外签名 → 先改 §3.2,再改代码。
-`PRD.md` 冲突 → 以 `PRD.md` 为准,回改本文;与共享 `docs/coding-standards.md` 冲突 → 以 docs/ 为准并回改本文。