feat: 简化技术描述语言(3~4)

This commit is contained in:
dayjoy
2025-08-20 11:20:58 +08:00
parent 47199b895c
commit 8d028d116c
+66 -55
View File
@@ -1404,73 +1404,84 @@ class CreateUserBto { //对应实体user
- 自定义查询时框架不自动生成代码(需要手动编写全部代码) - 自定义查询时框架不自动生成代码(需要手动编写全部代码)
- 各层代码位置严格遵守**3.2 项目结构与导航**,必须有mapper层、service层、DO对象、DTO对象,API返回数据必须有VO对象 - 各层代码位置严格遵守**3.2 项目结构与导航**,必须有mapper层、service层、DO对象、DTO对象,API返回数据必须有VO对象
### **3 生成代码产物补充说明** ### **3 代码生成说明**
- **3.1 支持的语言/框架**
Java、SpringBoot、MyBatis-plus(读)、Hibernate(写) **3.1 技术栈**
- **3.2 项目结构与导航** Java、SpringBoot、MyBatis-plus(读取)、Hibernate(写入)
TOCO生成的项目是一个多模块的SpringBoot项目,包括主模块和子模块,它的子模块位于根目录下的/modules目录中,**注意** 获取子模块代码文件路径的时候需要从根目录开始,所以必须从modules节点开始,例如:子模块module1下的的java类路径应该是`modules/module1/src/main/java...`
<dir> **3.2 项目结构**
|──main_module 多模块SpringBoot项目,子模块在`/modules`目录下。子模块路径必须从`modules`开始,如:`modules/module1/src/main/java...`
│ ├── common # 项目级别公共的基础模块
```
项目根目录
├── main_module
│ ├── common/ # 项目级公共模块
│ │ ├── config/ # 中间件配置 │ │ ├── config/ # 中间件配置
│ │ ├──constants/ # 项目级别常量 │ │ ├── constants/ # 项目常量
│ │ ├──enums/ # 项目级别枚举 │ │ ├── enums/ # 项目枚举
│ │ ├── redis/ # Redis配置 │ │ ├── redis/ # Redis配置
│ │ ├── response/ # 返回结果封装 │ │ ├── response/ # 返回结果封装
│ │ └──utils/ # 项目级别utils │ │ └── utils/ # 项目工具类
└── └── entrance/ # 项目入口 │ └── entrance/ # 项目入口
│ └──AppApplication.java # 项目启动类 │ └── AppApplication.java # 启动类
└── modules # 子模块列表 └── modules/ # 子模块列表
└── module1/ # 子模块1 └── module1/ # 子模块1
├── common/ ├── common/
│ ├── constants/ # 模块常量 │ ├── constants/ # 模块常量
│ ├──utils/ #模块级别utils │ ├── utils/ # 模块工具类
│ └──enums/ # 枚举 │ └── enums/ # 模块枚举
├── entrance/web/src/main/java/com/{project_name}/{module_name}/entrance/web/ ├── entrance/web/src/main/java/com/{项目名}/{模块名}/entrance/web/
│ ├──controller/ # api 定义 │ ├── controller/ # API定义
│ ├──converter/ # 把DTO转化成VO │ ├── converter/ # DTO转VO
│ ├──vo/ # VO结构定义 │ ├── vo/ # VO结构
│ └── query/ # 把读方案返回的数据转成成VO │ └── query/ # 读方案转VO
│ ├── assembler/ # VO的数据填充 │ ├── assembler/ # VO数据填充
│ ├── collector/ # 读方案返回的id数据展开成完成对象数据 │ ├── collector/ # ID数据展开为完整对象
│ └── executor/ # 调用Service的度方案实现,同时调用collector和assembler,返回最终的VO │ └── executor/ # 调用Service实现,返回VO
├── manager/src/main/java/com/{project_name}/{module_name}/manager/ ├── manager/src/main/java/com/{项目名}/{模块名}/manager/
│ ├── bo/ # 聚合对象定义 │ ├── bo/ # 聚合对象定义
│ │ └── base/ # 聚合对象的基类 │ │ └── base/ # 聚合对象基类
│ ├── dto/ # 数据传输对象定义 │ ├── dto/ # DTO定义
│ ├── converter/ # 复杂Dto(非BaseDto)组装 │ ├── converter/ # 复杂DTO组装
│ ├── facade/ # 调用其他模块的RPC适配器,包含RpcAdapter,如UserDtoServiceInMeetingRpcAdapter,表示从meeting模块调用user模块中方法 │ ├── facade/ # 跨模块RPC适配器
│ └── impl/ # Dto的查询接口的实现 │ └── impl/ # DTO查询实现
├── persist/src/main/java/com/{project_name}/{module_name}/persist/ ├── persist/src/main/java/com/{项目名}/{模块名}/persist/
│ ├── eo/ # 值对象(Eo)的结构定义 │ ├── eo/ # 值对象定义
│ ├── dos/ # 数据库单表结构的映射 │ ├── dos/ # 数据库表映射
│ ├── qto/ # 读方案的数据库查询实现 │ ├── qto/ # 读方案数据库查询
│ └── mapper/ # MyBatis的Mapper定义 │ └── mapper/ # MyBatis Mapper
└── service/src/main/java/com/{project_name}/{module_name}/service/ # BOService(包含某个聚合下所有写方案生成的方法)、 DtoService(包含DTO生成的预定义方法) └── service/src/main/java/com/{项目名}/{模块名}/service/
├── bto/ # 写方案入参的定义 ├── bto/ # 写方案入参定义
├── converter/ # 对返回的BaseDto按需进行二次扩展 ├── converter/ # BaseDto扩展
├── query/ # 查询方案的service层入口,调用persist层的查询实现 ├── query/ # 查询方案Service入口
└── base/ # 每个BOService对应的基类 └── base/ # BOService基类
在一个子模块的内,它的依赖层级为entrance -> service -> manager -> persist, 同时各个层都依赖 common
</dir> 模块依赖层级:entrance -> service -> manager -> persist,各层都依赖common
- **3.3 标准查找流程** ```
**3.3 查找路径**
1. **API查找** → `modules/{模块名}/entrance/web/controller/` 1. **API查找** → `modules/{模块名}/entrance/web/controller/`
2. **DTO查找** → `modules/{模块名}/manager/dto/` 2. **DTO查找** → `modules/{模块名}/manager/dto/`
3. **Service查找** → `modules/{模块名}/service/` 3. **Service查找** → `modules/{模块名}/service/`
4. **数据层查找** → `modules/{模块名}/persist/ 4. **数据层查找** → `modules/{模块名}/persist/`
- **3.4 特殊注解及含义**
TOC自动生成的类和方法会带有@AutoGenerated注解,注解中有2个属性:locked为boolean类型,如果locked=true,则代表该文件或方法不建议修改;uuid为String类型,表示该类或方法的唯一标识,如果uuid中包含|字符,则说明该uuid为特殊格式,由不同类型的数据拼装而成(见**[3.2 设计元素到代码的映射规则及修改建议]**中每种设计元素的代码说明)。 **3.4 特殊注解**
- **3.5 代码严格分层** 自动生成的类和方法有`@AutoGenerated`注解:
Service层方法不能返回VO,不能调用任何Controller层的方法,如VoQueryExecutor、VoConverter等 - `locked`属性:true表示不建议修改
- `uuid`属性:唯一标识,包含`|`字符表示特殊格式拼装
**3.5 分层规则**
Service层方法不能返回VO,不能调用Controller层方法(如VoQueryExecutor、VoConverter等)
### 4. TOCO 最佳实践 ### 4. TOCO 最佳实践
#### 4.1 接口参数类型和返回值选择(Interface Parameter & Return Type Definition): #### 4.1 接口参数类型和返回值选择:
在做TOCO接口(API、RPC)设计时,通常会先判断接口的主要功能是读数据库或写数据库,并分析相关的读写方案以及对应的QTO和BTO。如果是读场景,则参数会**优先使**用相关的QTO;如果是写场景,则参数会**优先**使用相关的BTO,如果BTO和QTO无法满足要求,则可以再增加基本类型或Enum、EO等类型参数。参数类型选择时必须遵循以下要求:a.DTO、VO不能作为参数类型;b.QTO、BTO不能作为返回值类型。 设计TOCO接口(API、RPC)时,先判断主要功能是读库还是写库,分析对应的读写方案及QTO、BTO。读场景**优先**使用QTO作参数;写场景**优先**使用BTO作参数。QTO、BTO不满足时,可增加基本类型、Enum、EO参数。必须遵循:a.DTO、VO不能作参数;b.QTO、BTO不能作返回值。
**重要说明:** **重要说明:**
- 本章节描述的是参数选择的**优先级原则**,不是绝对限制 - 本节描述参数选择的**优先级原则**,非绝对限制
- API参数的绝对限制请参考2.14章节 - API参数绝对限制见2.14章节
- "优先使用QTO/BTO"意思是在满足规范的前提下,根据场景选择最合适的参数类型 - "优先使用QTO/BTO"指在满足规范前提下,根据场景选择最合适的参数类型
#### 4.2 在处理先读,后更新的场景的时候,为了避免并发引起的数据脏写,应该充分利用BoService的校验功能。 例如:在账户扣钱的情况,为了避免账户在并发扣除余额不足,在用raw sql实现中,我们一般会 通过 update account set balance = balance - amount where user_id = xxx and blance > amount 的 where 条件保护;在toco中,
应该1、在写方案中使用incr字段。 2、 在boService中,添加类似保护代码 if(userBo.getBalance >= 0) 进行保护;或则通过userBo的业务不变性(聚合校验),添加balance>=0的校验 #### 4.2 并发数据保护最佳实践:
处理先读后更新场景时,为避免并发导致数据脏写,应充分利用BoService校验功能。例如:账户扣钱场景,避免并发扣除导致余额不足,传统raw sql用 `update account set balance = balance - amount where user_id = xxx and balance > amount` 的where条件保护;在TOCO中,应该:1、写方案中使用incr字段。2、在boService中添加保护代码 `if(userBo.getBalance() >= 0)` 或通过userBo业务不变性(聚合校验)添加 `balance>=0` 校验。
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
</TOCO知识库> </TOCO知识库>