器 | 通用消息路由

一、引言

最近在实现微信小程序时,需要处理微信服务器推送来的不同的消息,消息类型多种多样,包括订阅消息、图文消息等等。在借鉴一些大神的设计模式后,简单实现了一种消息路由模型,可满足多种类型的消息、多种路由匹配、多种消息处理。

二、模型

image.png

  • 消息本身有一些特征量,可作为消息路由规则匹配的依据。

  • 一个消息路由器包含多个消息路由规则。

  • 一个消息路由规则包含拦截器、匹配器,多个处理器。

三、代码

3.1 消息定义

待消费的消息

@Builder @Getter @ToString public class Message { private String event; private String msgType; private String content; private String fromUser; private String toUser; private Instant createTime; //... as you wish }

待消费消息对象包含一些Trait字段,包括eventmsgTypecontent。这些字段既可以作为路由规则匹配的依据,也能作为具体消息处理的条件。可根据不同的业务类型去扩展。

消息处理结果

@Builder @ToString public class OutMessage { private String msgType; private String fromUser; private String toUser; private Instant createTime; }

消息处理结果,根据具体业务自行定义吧。

3.2 消息处理器

抽象类型

public interface MessageHandler { OutMessage handle(Message message, Map<String,Object> context); }

这是所有消息处理器的抽象类型,自定义的处理器都必须实现它。简单实现一个消息日志记录处理器。

@Component public class LogMessageHandler implements MessageHandler { @Override public OutMessage handle(Message message, Map<String, Object> context) { System.out.println(message.toString()); // define your return value return null; } }

3.2 路由相关

消息拦截器

public interface MessageInterceptor { OutMessage handle(Message message, Map<String,Object> context); }

拦截器可增强对消息处理。自行实现此接口。

消息匹配器

public interface MessageRouterMatcher { boolean match(Message message); }

匹配器可实现对消息的过滤,以实现对消息的规则匹配。

路由器

``` public class MessageRouter {

@Getter
private final List<MessageRouterRule> rules = new ArrayList<>();

public MessageRouterRule rule(){
    return new MessageRouterRule(this);
}

private OutMessage route(Message message,Map<String,Object> context){
    final List<MessageRouterRule> matchRules = new ArrayList<>();
    final Iterator<MessageRouterRule> iterator = this.rules.iterator();
    while (iterator.hasNext()){
        final MessageRouterRule rule = iterator.next();
        if (rule.test(message)){
            matchRules.add(rule);
        }
    }
    if(matchRules.size() == 0){
        return null;
    }else{
        final Iterator<MessageRouterRule> matchIterator = matchRules.iterator();
        while (matchIterator.hasNext()){
            final MessageRouterRule rule = matchIterator.next();
            //think think multi  OutMessage
            return rule.service(message, context);
        }
    }
    return null;
}

public OutMessage route(Message message){
    return this.route(message,new HashMap<>(2));
}

} ```

消息路由规则

``` public class MessageRouterRule {

//是否异步处理消息
private boolean async;
private String event;
private String msgType;
private String content;
private String fromUser;
private String toUser;

/**
 * 路由器
 */
private MessageRouter router;
/**
 * 匹配器
 */
private MessageRouterMatcher matcher;
/**
 * 处理器
 */
private List<MessageHandler> handlers = new ArrayList<>();
/**
 * 拦截器 
 */
private List<MessageInterceptor> interceptors = new ArrayList<>();


public MessageRouterRule async(boolean async){
    this.async = async;
    return this;
}

public MessageRouterRule msgType(String msgType){
    this.msgType = msgType;
    return this;
}

public MessageRouterRule event(String event){
    this.event = event;
    return this;
}

public MessageRouterRule content(String content){
    this.content= content;
    return this;
}

public MessageRouterRule fromUser(String fromUser){
    this.fromUser= fromUser;
    return this;
}

public MessageRouterRule toUser(String toUser){
    this.toUser= toUser;
    return this;
}

public MessageRouterRule handler(MessageHandler handler,MessageHandler... otherHandlers){
    this.handlers.add(handler);
    if(otherHandlers != null && otherHandlers.length>0){
        Collections.addAll(this.handlers,otherHandlers);
    }
    return this;
}

public MessageRouterRule handle(MessageHandler handler){
    return this.handler(handler,(MessageHandler[]) null);
}

public MessageRouter end(){
    this.router.getRules().add(this);
    return this.router;
}

protected boolean test(Message message){
    //here can use matcher
    return (this.fromUser == null || this.fromUser.equals(message.getFromUser())) && (this.msgType == null || this.msgType.toLowerCase().equals(message.getMsgType() == null ? null : message.getMsgType().toLowerCase())) && (this.event == null || this.event.toLowerCase().equals(message.getEvent() == null ? null : message.getEvent().toLowerCase())) && (this.content == null || this.content.equals(message.getContent() == null ? null : message.getContent().trim())) && (this.matcher == null || this.matcher.match(message));
}

public MessageRouterRule(MessageRouter router){
    this.router = router;
}

protected OutMessage service(Message message, Map<String,Object> context){
    OutMessage outMessage = null;
    final Iterator<MessageHandler> iterator = handlers.iterator();
    while (iterator.hasNext()){
        final MessageHandler handler = iterator.next();
        if(null != handler){
            outMessage = handler.handle(message,context);
        }
    }
    return outMessage;
}

} ```

消息路由器中包含多种消息路由规则。

消息路由规则通过拦截器增强都消息的处理,通过匹配器实现对消息的过滤匹配。同时集成多个处理器,以完成对消息的最终处理。

四、测试

本次测试使用的是spring框架。

先实现一个配置类bean

``` @Configuration public class MessageRouterConfiguration {

final LogMessageHandler logMessageHandler;

public MessageRouterConfiguration(LogMessageHandler logMessageHandler) {
    this.logMessageHandler = logMessageHandler;
}

@Bean
@ConditionalOnMissingBean(value = MessageRouter.class)
public MessageRouter newRouter(){
    final MessageRouter messageRouter = new MessageRouter();
    //log print router rule
    messageRouter.rule().async(false).event("event").handle(logMessageHandler).end();
    //... add more
    return messageRouter;
}

} ```

消息路由调用

在应用入口路由消息,得到结果

final OutMessage outMessage = router.route(message);

最终在终端会打印日志信息。

五、总结

本模型只实现了一个简单的消息路由模型,还有很多待完善的地方,例如

  • 处理多个消息处理器的执行结果
  • 异步处理消息
  • 消息可能会重复消费
  • ...

等下一个迭代再优化吧!欢迎留言沟通。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值