From c10ab1753a78fe9a468ad3ce7c590ad12bd1f315 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 22 Jan 2021 21:50:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20Redis=20pub/sub=20?= =?UTF-8?q?=E7=9A=84=E5=B0=81=E8=A3=85=EF=BC=8C=E6=8F=90=E5=8D=87=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E4=BE=BF=E5=88=A9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listener/AbstractMessageListener.java | 54 +++++++++++++++++++ .../mq/consumer/SysMenuRefreshConsumer.java | 16 ++++-- .../producer/permission/SysMenuProducer.java | 7 +-- .../dashboard/util/json/JSONUtils.java | 23 ++++---- 4 files changed, 83 insertions(+), 17 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/framework/redis/core/listener/AbstractMessageListener.java b/src/main/java/cn/iocoder/dashboard/framework/redis/core/listener/AbstractMessageListener.java index d0f199c7b..8c95aecb0 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/redis/core/listener/AbstractMessageListener.java +++ b/src/main/java/cn/iocoder/dashboard/framework/redis/core/listener/AbstractMessageListener.java @@ -1,14 +1,31 @@ package cn.iocoder.dashboard.framework.redis.core.listener; +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.dashboard.util.json.JSONUtils; +import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; + +import java.lang.reflect.Type; /** * Redis Pub/Sub 监听器抽象类,用于实现广播消费 * + * @param 消息类型。一定要填写噢,不然会报错 + * * @author 芋道源码 */ public abstract class AbstractMessageListener implements MessageListener { + /** + * 消息类型 + */ + private final Class messageType; + + protected AbstractMessageListener() { + this.messageType = getMessageClass(); + } + /** * 获得 Sub 订阅的 Redis Channel 通道 * @@ -16,4 +33,41 @@ public abstract class AbstractMessageListener implements MessageListener { */ public abstract String getChannel(); + @Override + public final void onMessage(Message message, byte[] bytes) { + T messageObj = JSONUtils.parseObject(message.getBody(), messageType); + this.onMessage(messageObj); + } + + /** + * 处理消息 + * + * @param message 消息 + */ + public abstract void onMessage(T message); + + /** + * 通过解析类上的泛型,获得消息类型 + * + * @return 消息类型 + */ + @SuppressWarnings("unchecked") + private Class getMessageClass() { + Class targetClass = getClass(); + while (targetClass.getSuperclass() != null) { + // 如果不是 AbstractMessageListener 父类,继续向上查找 + if (targetClass.getSuperclass() != AbstractMessageListener.class) { + targetClass = targetClass.getSuperclass(); + continue; + } + // 如果是 AbstractMessageListener 父类,则解析泛型 + Type[] types = ((ParameterizedTypeImpl) targetClass.getGenericSuperclass()).getActualTypeArguments(); + if (ArrayUtil.isEmpty(types)) { + throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); + } + return (Class) types[0]; + } + throw new IllegalStateException(String.format("类型(%s) 找不到 AbstractMessageListener 父类", getClass().getName())); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/SysMenuRefreshConsumer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/SysMenuRefreshConsumer.java index c252cdd7d..fd88df11c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/SysMenuRefreshConsumer.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/SysMenuRefreshConsumer.java @@ -2,15 +2,23 @@ package cn.iocoder.dashboard.modules.system.mq.consumer; import cn.iocoder.dashboard.framework.redis.core.listener.AbstractMessageListener; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysMenuRefreshMessage; -import org.springframework.data.redis.connection.Message; +import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import javax.annotation.Resource; + @Component -public class SysMenuRefreshConsumer extends AbstractMessageListener { +@Slf4j +public class SysMenuRefreshConsumer extends AbstractMessageListener { + + @Resource + private SysMenuService menuService; @Override - public void onMessage(Message message, byte[] bytes) { - System.out.println(message); + public void onMessage(SysMenuRefreshMessage message) { + log.info("[onMessage][收到 Menu 刷新消息]"); + menuService.init(); } @Override diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java index c3450f8c5..240886d2b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/permission/SysMenuProducer.java @@ -1,7 +1,8 @@ package cn.iocoder.dashboard.modules.system.mq.producer.permission; import cn.iocoder.dashboard.modules.system.mq.message.permission.SysMenuRefreshMessage; -import org.springframework.data.redis.core.RedisTemplate; +import cn.iocoder.dashboard.util.json.JSONUtils; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -13,14 +14,14 @@ import javax.annotation.Resource; public class SysMenuProducer { @Resource - private RedisTemplate redisTemplate; + private StringRedisTemplate stringRedisTemplate; /** * 发送 {@link SysMenuRefreshMessage} 消息 */ public void sendMenuRefreshMessage() { SysMenuRefreshMessage message = new SysMenuRefreshMessage(); - redisTemplate.convertAndSend(SysMenuRefreshMessage.TOPIC, message); + stringRedisTemplate.convertAndSend(SysMenuRefreshMessage.TOPIC, JSONUtils.toJSONString(message)); } } diff --git a/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java b/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java index 07ad0e9a0..85633751f 100644 --- a/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java +++ b/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java @@ -1,5 +1,7 @@ package cn.iocoder.dashboard.util.json; +import com.alibaba.fastjson.JSON; + /** * JSON 工具类 * @@ -7,15 +9,16 @@ package cn.iocoder.dashboard.util.json; */ public class JSONUtils { -// public static Map toJSONMap(Object javaObject) { -// return (Map) JSON.toJSON(javaObject); -// } -// -// public static void main(String[] args) { -// SysDictTypeCreateReqVO createReqVO = new SysDictTypeCreateReqVO(); -// createReqVO.setType("1"); -// createReqVO.setRemark("2"); -// System.out.println(toJSONMap(createReqVO)); -// } + public static String toJSONString(Object object) { + return JSON.toJSONString(object); + } + + public static T parseObject(String text, Class clazz) { + return JSON.parseObject(text, clazz); + } + + public static T parseObject(byte[] bytes, Class clazz) { + return JSON.parseObject(bytes, clazz); + } }