feat: 简化技术描述语言(2.12~2.16)

This commit is contained in:
dayjoy
2025-08-20 11:18:10 +08:00
parent f253b4f628
commit 47199b895c

View File

@@ -1174,40 +1174,42 @@ private BO bo;
}
```
#### **2.12 业务变更传输对象(BTO)**
- **定义与用途:** 在TOCO中BTO写方案自动生成的参数结构,每个写方案生成一个BTO。BTO为写方案选定的操作实体根据关系形成的树形集合,最外层为聚合根。写方案调用方按BTO结构向写方案生成的RPC方法传入需要操作的实体字段值,完成数据库写操作
- **如何创建/生成:** BTO只能由写方案自动创建不能单独新建任何BTO。在创建写方案后TOCO自动生成一个BTO作为该写方案传入的参数结构
- **关键配置:** 名称(${WritePlanName}Bto驼峰展示),嵌套树形实体和字段列表,BTO内部的字段全部来自Entity。以下为一个示例:
<code>
class CreateUserBto { //对应实体user
Long id; //来自于user.id
String name; //来自user.name
#### **2.12 业务变更传输对象(BTO)**
- **定义与用途:** BTO写方案自动生成的参数结构每个写方案生成一个BTO。BTO将操作实体按关系组成树形集合,聚合根在最外层。调用方按BTO结构传入实体字段值,完成数据库写操作
- **创建方式:** BTO只能由写方案自动创建不能单独新建创建写方案后TOCO自动生成对应BTO作为参数结构
- **关键配置:** 名称(${WritePlanName}Bto驼峰命名嵌套树形实体和字段列表字段全部来自Entity。示例
```java
class CreateUserBto { //对应实体user
Long id; //来自user.id
String name; //来自user.name
List<PictureBto> pictureList;
class PictureBto { //对应实体picture
String url; //来自picture.url
String url; //来自picture.url
}
}
</code>
- **与API的关系:** BTO通常可作为API的参数API接收到参数后可直接透传给内部的RPC进行调用注意BTO只用作写操作的参数**禁止用作查询参数结构**
- **复杂场景处理:** 对于涉及多个写方案的复杂API可以
a. 如果接口有一个主要的写场景则创建一个主要的写方案让其自动生成的BTO作为API参数然后再增加其他基本类型的参数或EO
b. 使用基本类型参数或EO作为参数在接口执行流程中将基本类型参数转换为各个写方案自动生成的BTO再调用多个写方案
c. 如果流程过于复杂,优先考虑使用基本类型参数或EO
}
```
- **与API关系:** BTO可作API参数API接收参数后直接透传给内部RPC调用。BTO只用于写操作参数**禁止用作查询参数结构**
- **复杂场景处理:** 涉及多个写方案的复杂API可以
a. 有主要写场景时创建主要写方案用其生成的BTO作API参数再增加其他基本类型参数或EO
b. 用基本类型参数或EO作参数在接口流程中将参数转换为各写方案生成的BTO再调用多个写方案
c. 流程过于复杂时优先考虑使用基本类型参数或EO
#### **2.13 服务层方法 (RPC)**
- **定义与用途:** TOCO中RPC服务层方法。RPC按照可见性可以分为两种一种是公开RPC,可以被其他模块订阅订阅后可以通过RPC适配器进行调用;另一种是非公开RPC只能当前模块调用。非公开RPC可以被公开,从而被其他模块订阅并调
- **如何创建/生成:** RPC有4种创建方式a.DTO创建后会自动创建RPCRPC的公开性与DTO的公开性保持一致b.返回DTO的读方案根据分页情况、以及是否生成计数函数的配置自动生成非公开RPC c.写方案创建后自动生成非公开RPC返回值为操作的聚合根实体记录的主键字段的值 d.如果上述三种RPC无法满足需求则可以通过TOCO创建自定义RPC完整指定功能,需指定具体的参数返回值以及公开性等。
- **优先复用** 用户需要创建一个RPC时如果用户有明确要求创建的方式,则按照用户的要求创建。如果没有明确要求则通常先判断是否可以通过创建读方案、写方案、DTO来使TOCO自动创建出对应的RPC最后考虑通过TOCO创建自定义RPC
- **自定义RPC和代码中手写方法关系** 者都可以通过手动的方式实现一个服务层方法,应用场景的区别在于:如果一个方法需要被其他模块订阅,则通常使用自定义RPC如果一个方法只是某个API私有调用不需要外部模块开放,则可以使用代码手写方法
- **关键配置:** 类名(驼峰首字母大写以Service结尾)、是否公开、方法名(驼峰,首字母小写)、请求参数、返回值。注意如果一个RPC是分页查询参数为Qto类型Qto中已经包含了分页所需的from、size、scrollId属性,无需额外为RPC增加类似参数
- **TOCO中RPC存储:** 注意RPC在TOCO中只存储方法签名,不存储内部的执行流程逻辑,如果需要了解其内部的实现逻辑,则需要通过阅读RPC对应代码
- **参数类型:** RPC参数**只能**为QTO、BTO、Enum、基本类型可为单值或列表。注意如果是对象类型,则优先使用QTO、BTO作为参数**禁止使用**VO和自定义结构如Object
- **返回值类型:** RPC返回值**只能**为DTO、Enum、基本类型,可为单值或列表,**禁止使用**VO、QTO、BTO、自定义结构如Object作为返回值。注意如果是对象类型,则优先使用DTO作为返回值
- **TOCO中json结构描述:** TOCO中DTO使用一个json结构表示,示例如下
- **定义与用途:** TOCO中RPC服务层方法。分两种:公开RPC被其他模块订阅并通过适配器调用非公开RPC只能当前模块调用。非公开RPC可变为公开供其他模块使
- **创建/生成方式:** RPC有4种创建方式a.创建DTO后自动生成RPC公开性与DTO一致b.返回DTO的读方案根据分页和计数配置自动生成非公开RPCc.写方案创建后自动生成非公开RPC返回聚合根实体主键值d.需求不满足时通过TOCO创建自定义RPC需指定参数返回值公开性
- **优先复用:** 用户需要创建RPC时有明确要求要求创建。无明确要求时先判断能否通过读方案、写方案、DTO自动创建RPC最后考虑自定义RPC
- **自定义RPC和手写方法关系:** 者都可手动实现服务层方法。区别:需要被其他模块订阅用自定义RPC只是API私有调用不需要外部开放用手写方法
- **关键配置:** 类名(驼峰首字母大写以Service结尾)、是否公开、方法名(驼峰,首字母小写)、请求参数、返回值。分页查询参数为Qto类型Qto已包含from、size、scrollId属性无需额外参数
- **TOCO中RPC存储:** RPC在TOCO中只存储方法签名不存储执行逻辑。了解实现逻辑需阅读RPC对应代码
- **参数类型:** RPC参数**只能**为QTO、BTO、Enum、基本类型可为单值或列表。对象类型优先用QTO、BTO**禁用**VO和自定义结构如Object
- **返回值类型:** RPC返回值**只能**为DTO、Enum、基本类型可为单值或列表,**禁用**VO、QTO、BTO、自定义结构如Object对象类型优先用DTO
- **TOCO中json结构:** TOCO中DTOjson表示示例
```json
{
"methodName": "saveUsers",
"className": "UserSaveService",
"className": "UserSaveService",
"requestParams":[
{
"name": "saveUserBtoList",
@@ -1222,23 +1224,22 @@ private BO bo;
}
}
```
结构中一些关键字段描述如下:
requestParams为请求参数列表response为返回结构requestParams中每个参数和response的结构相同其中name为参数名;type为参数类型参数类型取值范围为Boolean,String,Integer,Long,Float,Double,BigDecimal,Date,ByteArray,Enum,Eo,Dto,Qto,Bto,List,PageResult,Void其中参数不能为Void和PageResult如果不需要返回值则type设置为Void如果返回值为分页查询的结果则type设置为PageResult且innerType必为Dto对应代码中的VSQueryResult<XxxDto>description为描述typeUuid为参数对应类结构的UUID当type为Enum、Eo、Dto时传入该对象的uuid当type为Qto时传入对应读方案的uuid、当type为Bto时传入对应写方案的uuidinnerType为List内部类型当type为List或PageResult时包含该字段innerUuid为List内部类结构的UUID当type为List或PageResult且innerType为Enum、Eo、Dto时传入该对象的uuid当innerType为Qto时传入对应读方案的uuid、当innerType为Bto时传入对应写方案的uuid。
- **生成代码:** RPC会在service层中生成类文件及实现函数包含DTO自动生成的RPC如UserDtoService.getById(主键为id)或StaffBaseDtoService.getByStaffId(主键为staff_id)、读写方案自动生成的RPC如UserDtoQueryService.queryByListQto、UserBOService.createUser、自定义RPC如UserCustomService.customMethod。特别注意公开的RPC才可被其他模块使用RPC被订阅后会生成RpcAdapter适配器其他模块通过RpcAdapter才可调用该方法。如Order模块订阅了User模块的UserDtoService.getById则会在Order模块中生成UserDtoServiceInOrderRpcAdapter.getById方法Order模块中的代码必须通过@Resource private UserDtoServiceInOrderRpcAdapter userDtoServiceInOrderRpcAdapter;注入适配器后才可进行方法调用。这里**必须要注意**:变量的命名必须是类名的首字母小写,禁止使用其他变量名。
- **修改建议:** 建议修改RPC方法不建议修改RPC方法签名、适配器中的内容
关键字段requestParams为请求参数列表response为返回结构参数和response结构相同其中name为参数名type为参数类型取值Boolean,String,Integer,Long,Float,Double,BigDecimal,Date,ByteArray,Enum,Eo,Dto,Qto,Bto,List,PageResult,Void参数不能为Void和PageResult无返回值设为Void分页查询结果设为PageResult且innerType必为Dto对应VSQueryResult<XxxDto>description为描述typeUuid为类结构UUIDtype为Enum、Eo、Dto时传入对象uuidQto时传入读方案uuidBto时传入写方案uuidinnerType为List内部类型type为List或PageResult时包含innerUuid为List内部类结构UUIDtype为List或PageResult且innerType为Enum、Eo、Dto时传入对象uuidinnerType为Qto时传入读方案uuidBto时传入写方案uuid
- **生成代码:** RPC在service层生成类文件和实现函数包含DTO自动生成的RPC如UserDtoService.getById、读写方案自动生成的RPC如UserDtoQueryService.queryByListQto、UserBOService.createUser、自定义RPC如UserCustomService.customMethod。公开RPC才能被其他模块使用订阅后生成RpcAdapter适配器其他模块通过RpcAdapter调用。如Order模块订阅User模块的UserDtoService.getById在Order模块生成UserDtoServiceInOrderRpcAdapter.getById方法Order模块代码必须通过@Resource private UserDtoServiceInOrderRpcAdapter userDtoServiceInOrderRpcAdapter;注入适配器后调用。**必须注意**:变量命名必须是类名首字母小写,禁用其他变量名
- **修改建议:** 建议修改RPC方法不建议修改RPC方法签名、适配器内容
#### **2.14 应用程序接口 (API)**
- **定义与用途:** 在TOCO中API用于定义对外暴露的HTTP接口
- **如何创建/生成:** API一般为通过TOCO创建需指定具体的参数和返回值等。
- **TOCO中API的存储:** 注意API在TOCO只存储了其URI和方法签名不存储内部的执行流程逻辑如果需要了解其内部的实现逻辑则需要通过阅读API对应代码
- **关键配置:** uri(加粗展示,一般为/api/${moduleName}/xxx如/api/user/create,全局唯一。如果用户有特殊命名规则的话以用户要求为准)、类名(以Controller结尾)、方法名(驼峰,首字母小写)、请求参数、返回值。注意如果一个API是分页查询参数为Qto类型则Qto中已经包含了分页所需的from、size、scrollId属性,无需额外为API增加类似参数
- **参数类型:** API的参数**只能**为读方案自动生成的QTO、写方案自动生成的BTO、EO、Enum、基本类型可为单值或列表。注意如果是对象类型则优先使用读方案自动生成的QTO、写方案自动生成的BTO作为参数。**禁止使用**DTO和自定义结构如Object作为参数
- **返回值类型:** TOCO的API运行在自己的Java脚手架中脚手架会自动对API的返回值做一层对象包装code、message、data。所以在TOCO中API的返回值无需考虑返回码和错误信息只需考虑返回的数据本身。TOCO中API的返回值**只能**为VO、Enum、基本类型,可为单值或列表**禁止使用**DTO、QTO、BTO、自定义结构如Object作为返回值。注意如果是对象类型,则优先使用VO作为返回值。
- **TOCO中json结构描述:** 在TOCO中API使用一个json结构表示,示例如下
- **定义与用途:** API定义对外HTTP接口
- **创建方式:** 通过TOCO创建需指定参数和返回值
- **存储特点:** TOCO只存储URI和方法签名不存储执行逻辑。了解实现需阅读对应代码
- **关键配置:** uri(/api/${moduleName}/xxx如/api/user/create全局唯一)、类名(以Controller结尾)、方法名(驼峰小写)、请求参数、返回值。分页查询参数为Qto时,已包含from、size、scrollId属性无需额外参数
- **参数类型:** 只能为QTO、BTO、EO、Enum、基本类型可为单值或列表。对象类型优先用QTO、BTO。禁用DTO和自定义结构
- **返回值类型:** 脚手架自动包装返回值(code、message、data)。只能为VO、Enum、基本类型可为单值或列表。禁用DTO、QTO、BTO、自定义结构对象类型优先用VO
- **json结构:** API用json表示示例
```json
{
"methodName": "getUserMeetingList",
"className": "MeetingQueryController",
"className": "MeetingQueryController",
"usageScenario": "xxx",
"requestParams":[
{
@@ -1248,160 +1249,160 @@ requestParams为请求参数列表response为返回结构requestParams中
"uuid": "6351a4d4-0063-442f-abd7-a2df6d656988"
},
{
"name": "test",
"name": "test",
"description": "是否为测试请求",
"type": "Boolean"
}
],
"response": {
"type": "List",
"innerType": "Vo",
"innerType": "Vo",
"innerUuid": "1d58352b-5333-4509-aec2-1abc3fac9122"
}
}
```
结构中一些关键字段描述如下:
requestParams为请求参数列表response为返回结构requestParams中每个参数和response的结构相同其中name为参数名;type为参数类型参数类型取值范围为Boolean,String,Integer,Long,Float,Double,BigDecimal,Date,ByteArray,Enum,Eo,List,PageResult,Vo,Qto,Bto,Void其中参数不能为Void和PageResult如果不需要返回值则type设置为Void如果返回值为分页查询的结果则type设置为PageResult且innerType必为Vo对应代码中的VSQueryResult<XxxVo>description为描述typeUuid为参数对应类结构的UUID当type为Enum、Eo、Vo时传入该对象的uuid当type为Qto时传入对应读方案的uuid、当type为Bto时传入对应写方案的uuidinnerType为List内部类型当type为List时包含该字段innerUuid为List或PageResult内部类结构的UUID当type为List或PageResult且innerType为Enum、Eo、Vo时传入该对象的uuid当innerType为Qto时传入对应读方案的uuid、当innerType为Bto时传入对应写方案的uuid。
关键字段requestParams为请求参数列表response为返回结构。参数和response结构相同name为参数名type为参数类型(Boolean,String,Integer,Long,Float,Double,BigDecimal,Date,ByteArray,Enum,Eo,List,PageResult,Vo,Qto,Bto,Void参数不能为Void和PageResult无返回值设为Void分页结果设为PageResult且innerType必为Vo对应VSQueryResult<XxxVo>)description为描述typeUuid为类结构UUID(type为Enum、Eo、Vo时传入对象uuidQto时传入读方案uuidBto时传入写方案uuid)innerType为List内部类型(type为List时包含)innerUuid为List或PageResult内部类结构UUID(type为List或PageResult且innerType为Enum、Eo、Vo时传入对象uuidinnerType为Qto时传入读方案uuidBto时传入写方案uuid)
- **代码产物和修改建议**
- **生成代码** API会在entrance层生成Controller及对应API方法
- **修改建议** 建议修改API方法实现内容禁止直接修改API方法签名、URI**注意**如需修改API定义名称、出入参数、URL需要通过修改API设计元素实现
- **生成代码:** entrance层生成Controller及对应API方法
- **修改建议:** 建议修改API方法实现内容禁止直接修改API方法签名、URI。修改API定义需通过修改API设计元素实现
#### **2.15 流程服务FunctionFlow)**
- **定义与用途:** TOCO针对复杂业务拆解,定义了流程服务,把一个复杂的业务过程,根据业务逻辑内聚性合并逻辑功能,把流程分解成流程节点,最终构造出一个类似工作流逻辑流程;最终实现复杂业务流程分解,提升代码可维护性。TOCO内嵌流程引擎在Function_Flow生成代码后可以在流程引擎中执行
- **何时使用:**
- 如果一个API/RPC涉及写服务超过3个,则**必须**使用流程服务
- 用户要求使用流程服务
- **节点封装:**
- 因为TOCO是一个面向数据处理的系统以数据内聚为首要考虑因素;一个节点通常围绕一个核心写服务,包括取数的读服务,为写服务的入参进行数据处理转换,以及该写服务完成后的一些附属功能, 除了条件节点入参校验,最终数据返回节点,每节点至少包一个写服务。
- **关键配置:** 名称(小写字母+下划线),拆解复杂业务逻辑,如果业务流程比较简单,则不需要使用流程服务
- **如何创建/生成:**
- 流程不是逻辑伪代码,不需要表达全部逻辑细节相关内聚性,相似性的功能逻辑需要被封装到一个流程节点内;例如用户注册:创建用户需要,需要创建账号信息,需要创建用户信息,并且发送一个通知消息,这几个功能都属于创建用户相关信息,而且没有逻辑分叉,因此可以内聚在一个逻辑节点
- 流程节点之间的参数和返回值的传递通过一个统一上下文Context传递(在写代码的时候按需修改Context文件添加所需的字段)
- 定义了JSON结构,用于表达逻辑流。流程节点分为 “顺序节点”、“条件节点”,“选择节点”,"开始节点节点间通过有向边连接,表示逻辑的执行方向从开始节点开始,可达各节点。
- 节点的边的定义如下:顺序节点可以有多条入边,可以有多条出边(一个出边表示下一个执行节点,多条出边表示几个分支并发执行;条件节点可由多条入边可以有2条出边表示条件为TrueFalse两种逻辑分支;选择节点可以有多条入边,可以有多条出边每条出边表示一种选择路径;开始节点只能有一条出边,不能有入边;
- 条件节点只封装条件判断逻辑返回TRUE或者FALSE循环节点只封装条件判断逻辑返回TRUE或者FALSE选择节点只封装分支选择逻辑,返回下游分支节点名称
- 终止流程:直接抛异常
- 一般校验逻辑放在一个“顺序节点"中,如果校验失败,以异常的方式抛出
- 节点可复用,同样的功能可抽取出来封装到一个节点
- **流程服务设计元素的表达:**
- 以Json表达Json Schema 定义如下:
- **定义与用途** TOCO复杂业务拆解为流程节点,基于业务逻辑内聚性合并功能,构建工作流逻辑流程,提升代码可维护性。内嵌流程引擎执行生成代码。
- **使用场景:**
- API/RPC涉及写服务超过3个**必须**使用
- 用户要求使用
- **节点封装**
- 以数据内聚为首要考虑一个节点围绕一个核心写服务,包含读服务、数据处理转换、附属功能。除条件节点入参校验数据返回节点,每节点至少包一个写服务。
- **配置** 名称(小写字母+下划线),拆解复杂业务逻辑。简单业务流程无需使用。
- **创建方式:**
- 流程逻辑伪代码,不表达全部细节相关内聚、相似功能封装到一个节点内如用户注册:创建账号、用户信息、发送通知属于创建用户相关信息,逻辑分叉,内聚在一个节点。
- 节点间参数和返回值通过统一上下文Context传递(编码时按需修改Context文件添加字段)。
- JSON表达逻辑流。节点类型:顺序节点条件节点选择节点开始节点节点间通过有向边连接,表示执行方向从开始节点可达各节点。
- 边定义:顺序节点多条入边多条出边(一条出边为下个执行节点,多条并发执行分支);条件节点多条入边2条出边(True/False分支);选择节点多条入边多条出边(每条选择路径);开始节点一条出边入边
- 条件节点只封装判断逻辑返回TRUE/FALSE循环节点只封装判断逻辑返回TRUE/FALSE选择节点只封装分支选择逻辑返回下游分支节点名称
- 终止流程:直接抛异常
- 校验逻辑放在顺序节点中,失败则抛异常。
- 节点可复用,同功能可抽取封装到一个节点
- **表达方式**
- JSON表达Schema如下
```json
{
"type": "object","description": "流程服务设计元素", "required": [ "description","name","nodes","edges"],
"properties":
{
"name": { "type": "string", "description": "流程名称,英语描述,单词之间使用下划线分割,总称不超过32字符" },
"moduleName": {"type": "string", "description": "模块名称,创建流程时传入,指定流程服务所属模块"},
"uuid": {"type": "string", "description": "流程服务设计元素的uuid创建流程不传入,更新的时候必须传入"},
"description": {"type": "string", "description": "流程服务描述, 总长度控制在200字符"},
"name": { "type": "string", "description": "流程名称,英文,下划线分割不超过32字符" },
"moduleName": {"type": "string", "description": "模块名称,创建时传入,指定所属模块"},
"uuid": {"type": "string", "description": "uuid创建不传入,更新时必传"},
"description": {"type": "string", "description": "流程服务描述,不超过200字符"},
"nodes": {
"type": "array", "description": "流程服务的节点列表",
"type": "array", "description": "节点列表",
"items": {
"type": "object","description": "流程服务节点对象", "required": ["name", "type", "description"],
"type": "object","description": "节点对象", "required": ["name", "type", "description"],
"properties": {
"name": {"type": "string", "description": "节点名称, 英语描述,单词之间使用下划线分割,总称不超过32字符"},
"type": {"type": "string", "description": "节点 类型,可以是 PROCESS_NODE(顺序节点、SWITCH_NODE(选择节点)、CONDITION_NODE(条件节点,START_NODE(开始节点)"},
"description": {"type": "string", "description": "描述节点功能, 英语描述,单词之间使用下划线分割,总称不超过200字符" }
"name": {"type": "string", "description": "节点名称,英文,下划线分割不超过32字符"},
"type": {"type": "string", "description": "节点类型PROCESS_NODE(顺序节点)、SWITCH_NODE(选择节点)、CONDITION_NODE(条件节点)、START_NODE(开始节点)"},
"description": {"type": "string", "description": "节点功能描述,英文,下划线分割不超过200字符" }
}
}
},
"edges": {
"type": "array", "description": "流程服务的边列表",
"type": "array", "description": "边列表",
"items": {
"type": "object","description": "流程服务的边", "required": ["fromNode", "toNode"],
"type": "object","description": "边", "required": ["fromNode", "toNode"],
"properties": {
"fromNode": {"type": "string", "description": "边的开始节点名称"},
"toNode": {"type": "string", "description": "边的结束节点名称"},
"value": {"type": "boolean", "description": "可选,作为条件节点出边true值表示条件匹配分支,false表示条件不匹配分支; 作为循环节点出边true值表示进入循环false值表示退出循环"}
"fromNode": {"type": "string", "description": "始节点名称"},
"toNode": {"type": "string", "description": "结束节点名称"},
"value": {"type": "boolean", "description": "可选,条件节点出边true匹配分支false不匹配分支循环节点出边true进入循环false退出循环"}
}
}
}
}
}
```
- 例子:用户注册流程
<code>
{
"moduleName":"user",//该流程所属的模块
"name":"user_register",//定义该流程的功能
"description":"注册用户",//描述该流程的详细功能
"nodes": [ // 定义该流程包含的节点
- 示例:用户注册流程
```json
{
"name":"start",
"type":"START_NODE",
"description": "起始节点"
"moduleName":"user", // 该流程所属的模块
"name":"user_register", // 定义功能
"description":"注册用户", // 详细功能描述
"nodes": [ // 包含节点
{
"name":"start",
"type":"START_NODE",
"description": "起始节点"
},
{
"name":"check_user_registed",
"type":"CONDITION_NODE",
"description":"校验入参合法性;判断昵称是否重名;判断用户是否已注册"
},
{
"name": "create_user",
"description":"创建用户,发送'用户创建'消息, 给用户发送欢迎通知",
"type": "PROCESS_NODE"
},
{
"name":"return_user_info",
"description":"返回用户信息,返回推荐给用户可能感兴趣的好友",
"type":"PROCESS_NODE"
}
],
"edges": [
{
"fromNode": "start",
"toNode":"check_user_registed"
},
{
"fromNode":"check_user_registed",
"toNode":"create_user",
"value":false
},
{
"name":"check_user_registed",
"type":"CONDITION_NODE",
"description":"校验入参合法性;判断昵称是否重名;判断用户是否已注册"
},
{
"name": "create_user",
"descripiton":"创建用户,发送'用户创建'消息, 给用户发送欢迎通知",
"type": "PROCESS_NODE"
},
{
"name":"return_user_info",
"descripiton":"返回用户信息,返回推荐给用户可能感兴趣的好友",
"type":"PROCESS_NODE"
}
],
"edges": [
{
"fromNode": "start",
"toNode":"check_user_registed"
},
{
"fromNode":"check_user_registed",
"toNode":"create_user",
"value":false
},
{
"fromNode":"check_user_registed"
"toNode":"return_user_info",
"value":true
},
{
"fromNode":"create_user",
"toNode":"return_user_info"
"toNode":"return_user_info",
"value":true
},
{
"fromNode":"create_user",
"toNode":"return_user_info"
}
]
}
]
}
</code>
```
- **代码产物和修改建议**
- **FlowConfig**
* **生成产物:** 每个模块service层生成一个Java类负责注册模块下所有流程到执行器
* **命名规则:** 类名为${moduleName}FlowConfig
* **职责:** 应用启动的时候注册模块内所有流程服务到执行器
* **路径:** <code>**.service.flow</code>
* **生成产物** 每个模块service层生成Java类注册模块下所有流程到执行器
* **命名** ${moduleName}FlowConfig
* **职责** 应用启动注册模块内所有流程服务到执行器
* **路径** `**.service.flow`
- **Service**
* **生成产物:** service层的以模块名为类名前缀的${moduleName}FlowService中生成一个流程入口函数
* **函数命名规则:** 流程名为方法名为后缀:pubic void invoke${functionFlowName}(${functionFlowName}Context context)
* **职责:** 代码逻辑中使用该流程需要以该函数作为调用入口
* **路径:** <code>**.service</code>
* **唯一标识符位置:** 其对应的标识符在函数注解@AutoGenerated中指定, uuid规则: ${FunctionFlow在TOCO中的uuid}|FLOW|METHOD
* **生成产物** service层${moduleName}FlowService中生成流程入口函数
* **命名:** `public void invoke${functionFlowName}(${functionFlowName}Context context)`
* **职责** 代码逻辑中使用该流程调用入口
* **路径** `**.service`
* **标识:** 函数注解@AutoGenerateduuid规则${FunctionFlow的uuid}|FLOW|METHOD
- **FlowNode**
* **生成产物:** service层生成一个Java类 **注意** 每个FunctionFlow的开始节点(StartNode)不生成
* **命名规则:** ${nodeName}Node
* **入口函数命名:** pubic void process()
* **职责:** 用于封装内聚性业务逻辑
* **路径:** <code>service.flow.node.${functionFlowName}</code>
* **生成产物** service层生成Java类**注意**开始节点(StartNode)不生成
* **命名** ${nodeName}Node
* **入口函数** `public void process()`
* **职责** 封装内聚性业务逻辑
* **路径** `service.flow.node.${functionFlowName}`
- **FlowContext**
* **函数命名规则:** {nodeName}Node
* **职责:** 作为流程节点之间的参数传递(包括出参和入参),在实现业务逻辑的时候,按需在这个上下文类中添加所需的字段
* **路径:** <code>**.service.flow.context</code>
* **唯一标识符位置:** 其对应的标识符在类注解@AutoGenerated中指定, uuid规则: ${FunctionFlow在TOCO中的uuid}|FLOW|CONTEXT
- **例**
- 用户登录,在UserFlowService中生成一个函数invokeLoginFlow,该函数通过流程框架根据流程定义调用LoginNodeLoginNode封装用户登录逻辑LoginFlowContext封装了用户登录参数和结果。
- **修改建议:** 不修改 service 中的函数, 不修改FlowConfig, 可以修改FlowContext, 添加/修改出入参数, 修改FlowNode中具体业务逻辑。
* **命名:** ${functionFlowName}Context
* **职责** 流程节点参数传递(出参和入参)实现业务逻辑时按需在此类中添加字段
* **路径** `**.service.flow.context`
* **标识:** 类注解@AutoGenerateduuid规则${FunctionFlow的uuid}|FLOW|CONTEXT
- **例:**
- 用户登录UserFlowService中生成invokeLoginFlow函数通过流程框架根据流程定义调用LoginNodeLoginNode封装用户登录逻辑LoginFlowContext封装登录参数和结果。
- **修改建议:** 不修改service函数和FlowConfig,可修改FlowContext添加/修改出入参数修改FlowNode中具体业务逻辑。
#### **2.16 自定义查询**
- 读方案无法满足需求的情况下,可以使用自定义查询
- 自定查询使用复杂sql实现业务功能
- 自定义查询的数据访问层使用MyBatis、MyBatisPlus实现
- 自定查询的时候框架不自动生成任何代码需要模型编写全部代码
- 各层代码位置严格遵守章节:**3.2 项目结构与导航**必须有mapper层、service层、必须有DO对象、必须有DTO对象如果是API返回数据必须有VO对象
- 读方案无法满足需求时,使用自定义查询
- 自定查询使用复杂sql实现业务功能
- 数据访问层使用MyBatis、MyBatisPlus实现
- 自定查询框架不自动生成代码(需要手动编写全部代码)
- 各层代码位置严格遵守**3.2 项目结构与导航**必须有mapper层、service层、DO对象、DTO对象API返回数据必须有VO对象
### **3 生成代码产物补充说明**
- **3.1 支持的语言/框架**