I.はじめに
最近、WeChatアプレットを実装する場合、WeChatサーバーからプッシュされたさまざまなメッセージを処理する必要があります。メッセージには、サブスクリプションメッセージ、グラフィックメッセージなど、さまざまな種類があります。偉大な神々のいくつかのデザインパターンから学んだ後、単純なメッセージルーティングモデルが実装されます。これは、複数のタイプのメッセージ、複数のルーティングマッチング、および複数のメッセージ処理に対応できます。
二、モデル
-
メッセージ自体にはいくつかの特徴的な量があり、メッセージルーティングルールを照合するための基礎として使用できます。
-
メッセージルーターには、複数のメッセージルーティングルールが含まれています。
-
メッセージルーティングルールには、インターセプター、マッチャー、および複数のプロセッサーが含まれます。
三、コード
3.1メッセージの定義
ソースコード:https://segmentfault.com/a/1190000039689926
消費されるメッセージ
@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
などの分野を、event
、msgType
、content
。これらのフィールドは、ルーティングルールを照合するための基礎としてだけでなく、特定のメッセージを処理するための条件としても使用できます。さまざまな業種に応じて拡張できます。
メッセージ処理結果
@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;
}
}
メッセージルーターには、さまざまなメッセージルーティングルールが含まれています。
メッセージルーティングルールは、インターセプターを介したすべてのメッセージの処理を強化し、マッチャーを介してメッセージをフィルタリングおよび照合します。複数のプロセッサを同時に統合して、メッセージの最終処理を完了します。
4、テスト
このテストでは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);
最終的に、ログ情報は端末に印刷されます。
五数要約
このモデルは単純なメッセージルーティングモデルのみを実装しており、次のような改善すべき領域がまだたくさんあります。
- 複数のメッセージプロセッサの実行結果を処理する
- メッセージを非同期的に処理する
- メッセージは繰り返し消費される可能性があります
- ..。
次の反復が最適化されるのを待ちます!コミュニケーションのためのメッセージを残すことを歓迎します。