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