代码解耦工具包

注意事项

旧项目慎用
版本是1.10.2-SNAPSHOT 的版本,其中Redis经过了大的改动,需要中台环境是1.10.0以上的版本

简介

  • 为什么会有这个工具包,主要还是为了提高代码的扩展性,尤其在系统的业务越来越多了。例如我初始化一个企业,需要做菜单初始化、门户初始化、用户的初始化、角色初始化、部门初始化、套件的安装,这一系列的动作,后续也不知道会不会加。而套件的安装又涉及到用户组、参照项、流程、流水号,想这一部分,如果每次都要改动其中的代码对后续对接的人很复杂,不知道会不会有什么坑,所以就有了这个工具包来把他解耦,当然你说你用MQ也是可以的,就是看个人使用,同一个工程的还是不建议使用MQ的。
  • 可以通过定义类型、事件、匹配规则执行指定的方法。
  • 可以设置handler的Log日志输出,为什么这样会方便呢,首先是这样统一了一个日志的规范,然后每个业务处理自己的业务逻辑,互不影响,当然业务会有关联的就别尬黑了。
  • 支持异步执行
  • 支持排重检查(内存、Redis),也支持开发者自己定义排重的方法
  • 支持Last执行,指定last的handler会最后执行
  • 出现异常会打印错误日志

Maven 依赖

        <dependency>
            <groupId>cn.flyrise</groupId>
            <artifactId>pai-common-message</artifactId>
            <version>1.10.2-SNAPSHOT</version>
        </dependency>

关键代码说明

    //消息的排重,这里可以使用Redis,common包中还提供了内存的
    @Bean
    public MessageDuplicateChecker messageDuplicateChecker() {
        return new MessageRedisDuplicateChecker(redisTemplate);
    }

   //定义全局的路由规则配置
   @Bean
    public MessageRouter messageRouter() {
        final MessageRouter newRouter = new MessageRouter(messageDuplicateChecker());
        newRouter.rule().async(true).handler(new LogHandler()).next();
        newRouter.rule().msgType("staff").last(true).async(true).handler(new StaffHandler()).next();
        newRouter.rule().async(false).handler(new DeptHandler()).end();
        return newRouter;
    }

MessageRouterRule.class关键属性说明
msgType:消息类型
event:事件类型
async:是否异步
content:消息内容
rContent:内容正则匹配
last:是否最后执行

MessageRouter.class关键属性说明
next():表示配置继续,如上图我配置的第一个是日志然后最后.next(),然后后面再写了一个企业创建的handler。
end():表示结束,不会再往下执行了。
msgType:会匹配messageBean中的消息类型然后执行到对应的handler的方法

代码

路由配置

import cn.flyrise.common.api.MessageDuplicateChecker;
import cn.flyrise.common.api.MessageRouter;
import cn.flyrise.common.api.impl.MessageRedisDuplicateChecker;
import cn.flyrise.common.handler.LogHandler;
import cn.flyrise.pai.console.handler.event.CreateEnterpriseHandler;
import cn.flyrise.pai.console.model.constants.UnifyMessageConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;

/**
 * 统一消息驱动事件配置
 *
 * @author Y.zc
 * @data 2022/10/25 17:20
 * @since 1.8.0
 */
@Configuration
public class UnifyMessageConfiguration {

    @Resource
    private LogHandler logHandler;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private CreateEnterpriseHandler createEnterpriseHandler;

    @Bean
    public MessageDuplicateChecker messageDuplicateChecker() {
        return new MessageRedisDuplicateChecker(redisTemplate);
    }

    @Bean
    public MessageRouter messageRouter() {
        final MessageRouter newRouter = new MessageRouter(messageDuplicateChecker());
        //日志记录
        newRouter.rule().async(true).handler(logHandler).next();

        //企业创建
        newRouter.rule().async(false)
                .msgType(UnifyMessageConstants.EnterpriseMsgType.CREATE)
                .handler(createEnterpriseHandler)
                .end();

        return newRouter;
    }

}

handler逻辑代码编写

继承AbstractHandler,并实现handler方法就可以了,AbstractHandler支持泛型,注意泛型的使用

@Component
public class LogHandler extends AbstractHandler<String> {
    public LogHandler() {
    }

    public OutMessageBean handle(MessageBean<String> messageBean, Map<String, Object> context) {
        this.logger.info("\nLogHandler 接收到请求消息,内容:{}", JSONUtil.toJsonStr(messageBean));
        return null;
    }
}

@Component
public class DeptHandler extends AbstractHandler<DeptDTO> {


    @Override
    public OutMessageBean handle(MessageBean<DeptDTO> messageBean, Map<String, Object> context) {
        ThreadUtil.sleep(1000);
        StaticLog.info("\nDeptHandler 接收到请求消息,内容:{}", JSONUtil.toJsonStr(messageBean));
        return new OutMessageBean("dept");
    }

}

消息的发送

        MessageBean messageBean = new MessageBean<StaffDTO>();
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setId("1");
        staffDTO.setStaffName("zcy");
        staffDTO.setStaffPhone("13711687995");
        messageBean.setMsgType("staff");
        messageBean.setMsgId("1");
        messageBean.setContent(staffDTO);
        OutMessageBean out = newRouter.route(messageBean,null);
  • msgId 是用来判断是否重复的标识
  • msgType 用来匹配路由

结果展示

文档更新时间: 2024-03-25 11:23   作者:朱灿奕