diff --git a/knowledge.md b/knowledge.md index a2dfdf3..5ca6265 100644 --- a/knowledge.md +++ b/knowledge.md @@ -1407,6 +1407,67 @@ class CreateUserBto { //对应实体user - 自定义查询时框架不自动生成代码(需要手动编写全部代码) - 各层代码位置严格遵守**3.2 项目结构与导航**,必须有mapper层、service层、DO对象、DTO对象,API返回数据必须有VO对象 +#### **2.17 领域消息(DomainMessage)** +- **定义与用途:** TOCO支持领域消息,通过创建和订阅领域消息,可以监听聚合对象的状态变化(创建、删除、更新),TOCO会自动生成消息的发送逻辑 +- **关键配置:** 名称(小写字母+下划线), 由于消息是全局可见,所以TOCO限制了名称项目级别不能重复 +- **与聚合的关系:** 每个聚合下可以定义多个领域消息,每次可以监听聚合下面其中一个实体的状态变更 +- **如何创建/生成:** 创建领域消息,需要先去顶聚合,然后确定需要监听的实体以及监听的变更类型 +- **领域消息的定义表达** + - 以Json表达,Json Schema 定义如下: + ```json + { + "type": "object", "required": ["name","description", "bo", "entity", "action","fields"], + "properties": { + "name": {"type": "string", "description": "消息名称,单词之间使用下划线分割,总称不超过32个字符,一个模块的领域消息名称不能重复"}, + "description": {"type": "string", "description": "消息描述,不超过128个字符"}, + "bo": {"type": "string", "description": "聚合名称"}, + "entity": {"type": "string", "description": "监听的实体名称,必须归属于聚合"}, + "fields": {"type": "array", "description": "指定消息里返回的entity的字段对应的字段名称","items": {"type": "string", "description": "字段名称"}}, + "action": {"type": "string", "description": "监听的变更类型,可选值:create、update、delete"}, + "delayInSeconds": {"type": "integer", "description": "延迟时间,单位为秒, 如果希望消息延迟消费,则设置该字段, 例如: 订单下单后5分钟未支付,触发一个消息,则可以监听订单的创建状态,并且设置延迟时间5分钟,这样消息会在5分钟后被消费"}, + "uuid": {"type": "string", "description": "消息的uuid,在更新领域消息时传入,创建的时候不传"} + } + } + ``` +- **代码产物和修改建议** + - **发送逻辑** 会在相应聚合的实体中通过hibernate的监听器中实现消息的发生逻辑,**不能修改** + - **生成产物:** + - **生成:** 在manager层生成一个Java类,封装消息体 + - **命名规则:** 类名为${domainMessageName}Mo + - **职责:** 消息内容载体 + - **类路径:** ```**.manager.mo``` + - **唯一标识符位置:** 其对应的标识符在类注解@AutoGenerated中指定, uuid规则: ${DomainMessage在TOCO中的uuid}|DMO|DEFINITION + - **例子** + 用户聚合,包含了user实体, 用户实体有 user_id, user_name 字段,那么创建一个领域消息,名称为user_created,描述为用户创建成功,聚合名称为user,实体名称为user,监听的变更类型为create,返回的字段为user_id,user_name。则会生一个类: UserCreatedMo {Long userId;String userName;};特别的,对于update的监听,生成消息里会包含字段的前值,命名以old结尾, 例如:UserUpdatedMo {String userName ; String userNameOld;} + +#### **2.18 订阅消息 (SubscribeMessage)** +- **定义与用途:** TOCO支持订阅消息, 订阅消息后生成代码会生成消息消费的模板代码, 后续只需在对应的模板代码里填写业务逻辑,而无需关注如何订阅消息的代码逻辑 **注意**在TOCO中,消息订阅按照模块独立订阅:一个消息可以被多个模块订阅,同一个消息在一个模块中只能订阅一次 +- **订阅消息的定义表达** + - 以Json表达,Json Schema 定义如下: 通过msgId或者msgName指定订阅的消息 + ```json + { + "type": "object", "required": ["moduleName"], + "msgId": {"type": "string", "description": "消息id"}, + "msgName": {"type": "string", "description": "消息名称"}, + "moduleName": {"type": "string", "description": "模块名称,指定消息被订阅到哪个模块"} + } + ``` +- **代码产物和修改建议** + - **Consumer类** + - **命名规则:** 在指定模块的的service层生成一个Java类,封装了消息的消费类入口 + - **命名规则:** 类名为${messageName}Consumer + - **职责:** 消息的消费类入口 + - **类路径:** ```**.service.mq.consumer``` + - **MsgHandler函数** + - **命名规则:** 在Consumer类中生成一个函数,封装了消息的消费逻辑的函数入口 + - **命名规则:** 函数名为handleMessage + - **职责:** 消息的消费函数入口,该函数以对应的消息作为参数 + - **唯一标识符位置:** 其对应的标识符在函数@AutoGenerated中指定, uuid规则: ${模块id}_${DomainMessage在TOCO中的uuid} + - **修改建议** + - handleMessage函数中实现业务逻辑, 如果消费成功,返回ture; 处理失败返回false, 消息会被多次投递 + - 如果消息要实现幂等消费,则需要在handleMessage函数上添加@Transactional注解,同时在Consumer类中覆盖父函数 @Override boolean useDBIdempotentWithTransactional(){return true;}, 开启幂等机制 + + ### **3 代码生成说明** **3.1 技术栈**