diff --git a/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/CacheAutoConfiguration.java b/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/TashowCacheAutoConfiguration.java
similarity index 96%
rename from tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/CacheAutoConfiguration.java
rename to tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/TashowCacheAutoConfiguration.java
index dcb0e72..37c80f6 100644
--- a/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/CacheAutoConfiguration.java
+++ b/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/TashowCacheAutoConfiguration.java
@@ -19,7 +19,7 @@ import org.springframework.util.StringUtils;
import java.util.Objects;
-import static com.tashow.cloud.redis.config.RedisAutoConfiguration.buildRedisSerializer;
+import static com.tashow.cloud.redis.config.TashowRedisAutoConfiguration.buildRedisSerializer;
/**
@@ -28,7 +28,7 @@ import static com.tashow.cloud.redis.config.RedisAutoConfiguration.buildRedisSer
@AutoConfiguration
@EnableConfigurationProperties({CacheProperties.class, TashowCacheProperties.class})
@EnableCaching
-public class CacheAutoConfiguration {
+public class TashowCacheAutoConfiguration {
/**
* RedisCacheConfiguration Bean
diff --git a/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/RedisAutoConfiguration.java b/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/TashowRedisAutoConfiguration.java
similarity index 97%
rename from tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/RedisAutoConfiguration.java
rename to tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/TashowRedisAutoConfiguration.java
index 39a9ee7..116c615 100644
--- a/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/RedisAutoConfiguration.java
+++ b/tashow-framework/tashow-data-redis/src/main/java/com/tashow/cloud/redis/config/TashowRedisAutoConfiguration.java
@@ -14,7 +14,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
* Redis 配置类
*/
@AutoConfiguration(before = RedissonAutoConfigurationV2.class) // 目的:使用自己定义的 RedisTemplate Bean
-public class RedisAutoConfiguration {
+public class TashowRedisAutoConfiguration {
/**
* 创建 RedisTemplate Bean,使用 JSON 序列化方式
diff --git a/tashow-framework/tashow-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/tashow-framework/tashow-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index bcaa8a2..3b32e89 100644
--- a/tashow-framework/tashow-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/tashow-framework/tashow-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,2 +1,2 @@
-com.tashow.cloud.redis.config.RedisAutoConfiguration
-com.tashow.cloud.redis.config.CacheAutoConfiguration
+com.tashow.cloud.redis.config.TashowRedisAutoConfiguration
+com.tashow.cloud.redis.config.TashowCacheAutoConfiguration
diff --git a/tashow-framework/tashow-framework-mq/pom.xml b/tashow-framework/tashow-framework-mq/pom.xml
index 41a37c1..11b483f 100644
--- a/tashow-framework/tashow-framework-mq/pom.xml
+++ b/tashow-framework/tashow-framework-mq/pom.xml
@@ -21,22 +21,11 @@
tashow-data-redis
-
-
- org.springframework.kafka
- spring-kafka
- true
-
org.springframework.amqp
spring-rabbit
true
-
- org.apache.rocketmq
- rocketmq-spring-boot-starter
- true
-
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/package-info.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/package-info.java
new file mode 100644
index 0000000..356754a
--- /dev/null
+++ b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/package-info.java
@@ -0,0 +1 @@
+package com.tashow.cloud.mq;
\ No newline at end of file
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/config/RedisMQConsumerAutoConfiguration.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/config/RedisMQConsumerAutoConfiguration.java
deleted file mode 100644
index c26f4d2..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/config/RedisMQConsumerAutoConfiguration.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.tashow.cloud.mq.redis.config;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.system.SystemUtil;
-import com.tashow.cloud.common.enums.DocumentEnum;
-import com.tashow.cloud.mq.redis.core.RedisMQTemplate;
-import com.tashow.cloud.mq.redis.core.job.RedisPendingMessageResendJob;
-import com.tashow.cloud.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
-import com.tashow.cloud.mq.redis.core.stream.AbstractRedisStreamMessageListener;
-import com.tashow.cloud.redis.config.RedisAutoConfiguration;
-import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RedissonClient;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.connection.RedisServerCommands;
-import org.springframework.data.redis.connection.stream.Consumer;
-import org.springframework.data.redis.connection.stream.ObjectRecord;
-import org.springframework.data.redis.connection.stream.ReadOffset;
-import org.springframework.data.redis.connection.stream.StreamOffset;
-import org.springframework.data.redis.core.RedisCallback;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.listener.ChannelTopic;
-import org.springframework.data.redis.listener.RedisMessageListenerContainer;
-import org.springframework.data.redis.stream.StreamMessageListenerContainer;
-import org.springframework.scheduling.annotation.EnableScheduling;
-
-import java.util.List;
-import java.util.Properties;
-
-/**
- * Redis 消息队列 Consumer 配置类
- *
- * @author 芋道源码
- */
-@Slf4j
-@EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息
-@AutoConfiguration(after = RedisAutoConfiguration.class)
-public class RedisMQConsumerAutoConfiguration {
-
- /**
- * 创建 Redis Pub/Sub 广播消费的容器
- */
- @Bean
- @ConditionalOnBean(AbstractRedisChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听
- public RedisMessageListenerContainer redisMessageListenerContainer(
- RedisMQTemplate redisMQTemplate, List> listeners) {
- // 创建 RedisMessageListenerContainer 对象
- RedisMessageListenerContainer container = new RedisMessageListenerContainer();
- // 设置 RedisConnection 工厂。
- container.setConnectionFactory(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory());
- // 添加监听器
- listeners.forEach(listener -> {
- listener.setRedisMQTemplate(redisMQTemplate);
- container.addMessageListener(listener, new ChannelTopic(listener.getChannel()));
- log.info("[redisMessageListenerContainer][注册 Channel({}) 对应的监听器({})]",
- listener.getChannel(), listener.getClass().getName());
- });
- return container;
- }
-
- /**
- * 创建 Redis Stream 重新消费的任务
- */
- @Bean
- @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
- public RedisPendingMessageResendJob redisPendingMessageResendJob(List> listeners,
- RedisMQTemplate redisTemplate,
- @Value("${spring.application.name}") String groupName,
- RedissonClient redissonClient) {
- return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient);
- }
-
- /**
- * 创建 Redis Stream 集群消费的容器
- *
- * 基础知识:Redis Stream 的 xreadgroup 命令
- */
- @Bean(initMethod = "start", destroyMethod = "stop")
- @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
- public StreamMessageListenerContainer> redisStreamMessageListenerContainer(
- RedisMQTemplate redisMQTemplate, List> listeners) {
- RedisTemplate redisTemplate = redisMQTemplate.getRedisTemplate();
- checkRedisVersion(redisTemplate);
- // 第一步,创建 StreamMessageListenerContainer 容器
- // 创建 options 配置
- StreamMessageListenerContainer.StreamMessageListenerContainerOptions> containerOptions =
- StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder()
- .batchSize(10) // 一次性最多拉取多少条消息
- .targetType(String.class) // 目标类型。统一使用 String,通过自己封装的 AbstractStreamMessageListener 去反序列化
- .build();
- // 创建 container 对象
- StreamMessageListenerContainer> container =
- StreamMessageListenerContainer.create(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory(), containerOptions);
-
- // 第二步,注册监听器,消费对应的 Stream 主题
- String consumerName = buildConsumerName();
- listeners.parallelStream().forEach(listener -> {
- log.info("[redisStreamMessageListenerContainer][开始注册 StreamKey({}) 对应的监听器({})]",
- listener.getStreamKey(), listener.getClass().getName());
- // 创建 listener 对应的消费者分组
- try {
- redisTemplate.opsForStream().createGroup(listener.getStreamKey(), listener.getGroup());
- } catch (Exception ignore) {
- }
- // 设置 listener 对应的 redisTemplate
- listener.setRedisMQTemplate(redisMQTemplate);
- // 创建 Consumer 对象
- Consumer consumer = Consumer.from(listener.getGroup(), consumerName);
- // 设置 Consumer 消费进度,以最小消费进度为准
- StreamOffset streamOffset = StreamOffset.create(listener.getStreamKey(), ReadOffset.lastConsumed());
- // 设置 Consumer 监听
- StreamMessageListenerContainer.StreamReadRequestBuilder builder = StreamMessageListenerContainer.StreamReadRequest
- .builder(streamOffset).consumer(consumer)
- .autoAcknowledge(false) // 不自动 ack
- .cancelOnError(throwable -> false); // 默认配置,发生异常就取消消费,显然不符合预期;因此,我们设置为 false
- container.register(builder.build(), listener);
- log.info("[redisStreamMessageListenerContainer][完成注册 StreamKey({}) 对应的监听器({})]",
- listener.getStreamKey(), listener.getClass().getName());
- });
- return container;
- }
-
- /**
- * 构建消费者名字,使用本地 IP + 进程编号的方式。
- * 参考自 RocketMQ clientId 的实现
- *
- * @return 消费者名字
- */
- private static String buildConsumerName() {
- return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
- }
-
- /**
- * 校验 Redis 版本号,是否满足最低的版本号要求!
- */
- private static void checkRedisVersion(RedisTemplate redisTemplate) {
- // 获得 Redis 版本
- Properties info = redisTemplate.execute((RedisCallback) RedisServerCommands::info);
- String version = MapUtil.getStr(info, "redis_version");
- // 校验最低版本必须大于等于 5.0.0
- int majorVersion = Integer.parseInt(StrUtil.subBefore(version, '.', false));
- if (majorVersion < 5) {
- throw new IllegalStateException(StrUtil.format("您当前的 Redis 版本为 {},小于最低要求的 5.0.0 版本!" +
- "请参考 {} 文档进行安装。", version, DocumentEnum.REDIS_INSTALL.getUrl()));
- }
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/config/RedisMQProducerAutoConfiguration.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/config/RedisMQProducerAutoConfiguration.java
deleted file mode 100644
index 0b2a62a..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/config/RedisMQProducerAutoConfiguration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tashow.cloud.mq.redis.config;
-
-import com.tashow.cloud.mq.redis.core.RedisMQTemplate;
-import com.tashow.cloud.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.tashow.cloud.redis.config.RedisAutoConfiguration;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import java.util.List;
-
-/**
- * Redis 消息队列 Producer 配置类
- *
- * @author 芋道源码
- */
-@Slf4j
-@AutoConfiguration(after = RedisAutoConfiguration.class)
-public class RedisMQProducerAutoConfiguration {
-
- @Bean
- public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate,
- List interceptors) {
- RedisMQTemplate redisMQTemplate = new RedisMQTemplate(redisTemplate);
- // 添加拦截器
- interceptors.forEach(redisMQTemplate::addInterceptor);
- return redisMQTemplate;
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/RedisMQTemplate.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/RedisMQTemplate.java
deleted file mode 100644
index 6d79c41..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/RedisMQTemplate.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.tashow.cloud.mq.redis.core;
-
-import com.tashow.cloud.common.util.json.JsonUtils;
-import com.tashow.cloud.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.tashow.cloud.mq.redis.core.message.AbstractRedisMessage;
-import com.tashow.cloud.mq.redis.core.pubsub.AbstractRedisChannelMessage;
-import com.tashow.cloud.mq.redis.core.stream.AbstractRedisStreamMessage;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import org.springframework.data.redis.connection.stream.RecordId;
-import org.springframework.data.redis.connection.stream.StreamRecords;
-import org.springframework.data.redis.core.RedisTemplate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Redis MQ 操作模板类
- *
- * @author 芋道源码
- */
-@AllArgsConstructor
-public class RedisMQTemplate {
-
- @Getter
- private final RedisTemplate redisTemplate;
- /**
- * 拦截器数组
- */
- @Getter
- private final List interceptors = new ArrayList<>();
-
- /**
- * 发送 Redis 消息,基于 Redis pub/sub 实现
- *
- * @param message 消息
- */
- public void send(T message) {
- try {
- sendMessageBefore(message);
- // 发送消息
- redisTemplate.convertAndSend(message.getChannel(), JsonUtils.toJsonString(message));
- } finally {
- sendMessageAfter(message);
- }
- }
-
- /**
- * 发送 Redis 消息,基于 Redis Stream 实现
- *
- * @param message 消息
- * @return 消息记录的编号对象
- */
- public RecordId send(T message) {
- try {
- sendMessageBefore(message);
- // 发送消息
- return redisTemplate.opsForStream().add(StreamRecords.newRecord()
- .ofObject(JsonUtils.toJsonString(message)) // 设置内容
- .withStreamKey(message.getStreamKey())); // 设置 stream key
- } finally {
- sendMessageAfter(message);
- }
- }
-
- /**
- * 添加拦截器
- *
- * @param interceptor 拦截器
- */
- public void addInterceptor(RedisMessageInterceptor interceptor) {
- interceptors.add(interceptor);
- }
-
- private void sendMessageBefore(AbstractRedisMessage message) {
- // 正序
- interceptors.forEach(interceptor -> interceptor.sendMessageBefore(message));
- }
-
- private void sendMessageAfter(AbstractRedisMessage message) {
- // 倒序
- for (int i = interceptors.size() - 1; i >= 0; i--) {
- interceptors.get(i).sendMessageAfter(message);
- }
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/interceptor/RedisMessageInterceptor.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/interceptor/RedisMessageInterceptor.java
deleted file mode 100644
index 3cea3ff..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/interceptor/RedisMessageInterceptor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.tashow.cloud.mq.redis.core.interceptor;
-
-import com.tashow.cloud.mq.redis.core.message.AbstractRedisMessage;
-
-/**
- * {@link AbstractRedisMessage} 消息拦截器
- * 通过拦截器,作为插件机制,实现拓展。
- * 例如说,多租户场景下的 MQ 消息处理
- *
- * @author 芋道源码
- */
-public interface RedisMessageInterceptor {
-
- default void sendMessageBefore(AbstractRedisMessage message) {
- }
-
- default void sendMessageAfter(AbstractRedisMessage message) {
- }
-
- default void consumeMessageBefore(AbstractRedisMessage message) {
- }
-
- default void consumeMessageAfter(AbstractRedisMessage message) {
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/job/RedisPendingMessageResendJob.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/job/RedisPendingMessageResendJob.java
deleted file mode 100644
index 7ddd81d..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/job/RedisPendingMessageResendJob.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.tashow.cloud.mq.redis.core.job;
-
-import cn.hutool.core.collection.CollUtil;
-import com.tashow.cloud.mq.redis.core.RedisMQTemplate;
-import com.tashow.cloud.mq.redis.core.stream.AbstractRedisStreamMessageListener;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RLock;
-import org.redisson.api.RedissonClient;
-import org.springframework.data.domain.Range;
-import org.springframework.data.redis.connection.stream.*;
-import org.springframework.data.redis.core.StreamOperations;
-import org.springframework.scheduling.annotation.Scheduled;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * 这个任务用于处理,crash 之后的消费者未消费完的消息
- */
-@Slf4j
-@AllArgsConstructor
-public class RedisPendingMessageResendJob {
-
- private static final String LOCK_KEY = "redis:pending:msg:lock";
-
- /**
- * 消息超时时间,默认 5 分钟
- *
- * 1. 超时的消息才会被重新投递
- * 2. 由于定时任务 1 分钟一次,消息超时后不会被立即重投,极端情况下消息5分钟过期后,再等 1 分钟才会被扫瞄到
- */
- private static final int EXPIRE_TIME = 5 * 60;
-
- private final List> listeners;
- private final RedisMQTemplate redisTemplate;
- private final String groupName;
- private final RedissonClient redissonClient;
-
- /**
- * 一分钟执行一次,这里选择每分钟的35秒执行,是为了避免整点任务过多的问题
- */
- @Scheduled(cron = "35 * * * * ?")
- public void messageResend() {
- RLock lock = redissonClient.getLock(LOCK_KEY);
- // 尝试加锁
- if (lock.tryLock()) {
- try {
- execute();
- } catch (Exception ex) {
- log.error("[messageResend][执行异常]", ex);
- } finally {
- lock.unlock();
- }
- }
- }
-
- /**
- * 执行清理逻辑
- *
- * @see 讨论
- */
- private void execute() {
- StreamOperations ops = redisTemplate.getRedisTemplate().opsForStream();
- listeners.forEach(listener -> {
- PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), groupName));
- // 每个消费者的 pending 队列消息数量
- Map pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer();
- pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> {
- log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount);
- // 每个消费者的 pending消息的详情信息
- PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(groupName, consumerName), Range.unbounded(), pendingMessageCount);
- if (pendingMessages.isEmpty()) {
- return;
- }
- pendingMessages.forEach(pendingMessage -> {
- // 获取消息上一次传递到 consumer 的时间,
- long lastDelivery = pendingMessage.getElapsedTimeSinceLastDelivery().getSeconds();
- if (lastDelivery < EXPIRE_TIME){
- return;
- }
- // 获取指定 id 的消息体
- List> records = ops.range(listener.getStreamKey(),
- Range.of(Range.Bound.inclusive(pendingMessage.getIdAsString()), Range.Bound.inclusive(pendingMessage.getIdAsString())));
- if (CollUtil.isEmpty(records)) {
- return;
- }
- // 重新投递消息
- redisTemplate.getRedisTemplate().opsForStream().add(StreamRecords.newRecord()
- .ofObject(records.get(0).getValue()) // 设置内容
- .withStreamKey(listener.getStreamKey()));
- // ack 消息消费完成
- redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, records.get(0));
- log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId());
- });
- });
- });
- }
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/message/AbstractRedisMessage.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/message/AbstractRedisMessage.java
deleted file mode 100644
index 546934a..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/message/AbstractRedisMessage.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.tashow.cloud.mq.redis.core.message;
-
-import lombok.Data;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Redis 消息抽象基类
- *
- * @author 芋道源码
- */
-@Data
-public abstract class AbstractRedisMessage {
-
- /**
- * 头
- */
- private Map headers = new HashMap<>();
-
- public String getHeader(String key) {
- return headers.get(key);
- }
-
- public void addHeader(String key, String value) {
- headers.put(key, value);
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/pubsub/AbstractRedisChannelMessage.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/pubsub/AbstractRedisChannelMessage.java
deleted file mode 100644
index 3a46d92..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/pubsub/AbstractRedisChannelMessage.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.tashow.cloud.mq.redis.core.pubsub;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.tashow.cloud.mq.redis.core.message.AbstractRedisMessage;
-
-/**
- * Redis Channel Message 抽象类
- *
- * @author 芋道源码
- */
-public abstract class AbstractRedisChannelMessage extends AbstractRedisMessage {
-
- /**
- * 获得 Redis Channel,默认使用类名
- *
- * @return Channel
- */
- @JsonIgnore // 避免序列化。原因是,Redis 发布 Channel 消息的时候,已经会指定。
- public String getChannel() {
- return getClass().getSimpleName();
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java
deleted file mode 100644
index b64a550..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.tashow.cloud.mq.redis.core.pubsub;
-
-import cn.hutool.core.util.TypeUtil;
-import com.tashow.cloud.common.util.json.JsonUtils;
-import com.tashow.cloud.mq.redis.core.RedisMQTemplate;
-import com.tashow.cloud.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.tashow.cloud.mq.redis.core.message.AbstractRedisMessage;
-import lombok.Setter;
-import lombok.SneakyThrows;
-import org.springframework.data.redis.connection.Message;
-import org.springframework.data.redis.connection.MessageListener;
-
-import java.lang.reflect.Type;
-import java.util.List;
-
-/**
- * Redis Pub/Sub 监听器抽象类,用于实现广播消费
- *
- * @param 消息类型。一定要填写噢,不然会报错
- *
- * @author 芋道源码
- */
-public abstract class AbstractRedisChannelMessageListener implements MessageListener {
-
- /**
- * 消息类型
- */
- private final Class messageType;
- /**
- * Redis Channel
- */
- private final String channel;
- /**
- * RedisMQTemplate
- */
- @Setter
- private RedisMQTemplate redisMQTemplate;
-
- @SneakyThrows
- protected AbstractRedisChannelMessageListener() {
- this.messageType = getMessageClass();
- this.channel = messageType.getDeclaredConstructor().newInstance().getChannel();
- }
-
- /**
- * 获得 Sub 订阅的 Redis Channel 通道
- *
- * @return channel
- */
- public final String getChannel() {
- return channel;
- }
-
- @Override
- public final void onMessage(Message message, byte[] bytes) {
- T messageObj = JsonUtils.parseObject(message.getBody(), messageType);
- try {
- consumeMessageBefore(messageObj);
- // 消费消息
- this.onMessage(messageObj);
- } finally {
- consumeMessageAfter(messageObj);
- }
- }
-
- /**
- * 处理消息
- *
- * @param message 消息
- */
- public abstract void onMessage(T message);
-
- /**
- * 通过解析类上的泛型,获得消息类型
- *
- * @return 消息类型
- */
- @SuppressWarnings("unchecked")
- private Class getMessageClass() {
- Type type = TypeUtil.getTypeArgument(getClass(), 0);
- if (type == null) {
- throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
- }
- return (Class) type;
- }
-
- private void consumeMessageBefore(AbstractRedisMessage message) {
- assert redisMQTemplate != null;
- List interceptors = redisMQTemplate.getInterceptors();
- // 正序
- interceptors.forEach(interceptor -> interceptor.consumeMessageBefore(message));
- }
-
- private void consumeMessageAfter(AbstractRedisMessage message) {
- assert redisMQTemplate != null;
- List interceptors = redisMQTemplate.getInterceptors();
- // 倒序
- for (int i = interceptors.size() - 1; i >= 0; i--) {
- interceptors.get(i).consumeMessageAfter(message);
- }
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/stream/AbstractRedisStreamMessage.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/stream/AbstractRedisStreamMessage.java
deleted file mode 100644
index d254d84..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/stream/AbstractRedisStreamMessage.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.tashow.cloud.mq.redis.core.stream;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.tashow.cloud.mq.redis.core.message.AbstractRedisMessage;
-
-/**
- * Redis Stream Message 抽象类
- *
- * @author 芋道源码
- */
-public abstract class AbstractRedisStreamMessage extends AbstractRedisMessage {
-
- /**
- * 获得 Redis Stream Key,默认使用类名
- *
- * @return Channel
- */
- @JsonIgnore // 避免序列化
- public String getStreamKey() {
- return getClass().getSimpleName();
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/stream/AbstractRedisStreamMessageListener.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/stream/AbstractRedisStreamMessageListener.java
deleted file mode 100644
index bf30a9b..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/core/stream/AbstractRedisStreamMessageListener.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package com.tashow.cloud.mq.redis.core.stream;
-
-import cn.hutool.core.util.TypeUtil;
-import com.tashow.cloud.common.util.json.JsonUtils;
-import com.tashow.cloud.mq.redis.core.RedisMQTemplate;
-import com.tashow.cloud.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.tashow.cloud.mq.redis.core.message.AbstractRedisMessage;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.SneakyThrows;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.connection.stream.ObjectRecord;
-import org.springframework.data.redis.stream.StreamListener;
-
-import java.lang.reflect.Type;
-import java.util.List;
-
-/**
- * Redis Stream 监听器抽象类,用于实现集群消费
- *
- * @param 消息类型。一定要填写噢,不然会报错
- *
- * @author 芋道源码
- */
-public abstract class AbstractRedisStreamMessageListener
- implements StreamListener> {
-
- /**
- * 消息类型
- */
- private final Class messageType;
- /**
- * Redis Channel
- */
- @Getter
- private final String streamKey;
-
- /**
- * Redis 消费者分组,默认使用 spring.application.name 名字
- */
- @Value("${spring.application.name}")
- @Getter
- private String group;
- /**
- * RedisMQTemplate
- */
- @Setter
- private RedisMQTemplate redisMQTemplate;
-
- @SneakyThrows
- protected AbstractRedisStreamMessageListener() {
- this.messageType = getMessageClass();
- this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey();
- }
-
- @Override
- public void onMessage(ObjectRecord message) {
- // 消费消息
- T messageObj = JsonUtils.parseObject(message.getValue(), messageType);
- try {
- consumeMessageBefore(messageObj);
- // 消费消息
- this.onMessage(messageObj);
- // ack 消息消费完成
- redisMQTemplate.getRedisTemplate().opsForStream().acknowledge(group, message);
- // TODO 芋艿:需要额外考虑以下几个点:
- // 1. 处理异常的情况
- // 2. 发送日志;以及事务的结合
- // 3. 消费日志;以及通用的幂等性
- // 4. 消费失败的重试,https://zhuanlan.zhihu.com/p/60501638
- } finally {
- consumeMessageAfter(messageObj);
- }
- }
-
- /**
- * 处理消息
- *
- * @param message 消息
- */
- public abstract void onMessage(T message);
-
- /**
- * 通过解析类上的泛型,获得消息类型
- *
- * @return 消息类型
- */
- @SuppressWarnings("unchecked")
- private Class getMessageClass() {
- Type type = TypeUtil.getTypeArgument(getClass(), 0);
- if (type == null) {
- throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
- }
- return (Class) type;
- }
-
- private void consumeMessageBefore(AbstractRedisMessage message) {
- assert redisMQTemplate != null;
- List interceptors = redisMQTemplate.getInterceptors();
- // 正序
- interceptors.forEach(interceptor -> interceptor.consumeMessageBefore(message));
- }
-
- private void consumeMessageAfter(AbstractRedisMessage message) {
- assert redisMQTemplate != null;
- List interceptors = redisMQTemplate.getInterceptors();
- // 倒序
- for (int i = interceptors.size() - 1; i >= 0; i--) {
- interceptors.get(i).consumeMessageAfter(message);
- }
- }
-
-}
diff --git a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/package-info.java b/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/package-info.java
deleted file mode 100644
index cc39879..0000000
--- a/tashow-framework/tashow-framework-mq/src/main/java/com/tashow/cloud/mq/redis/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 消息队列,基于 Redis 提供:
- * 1. 基于 Pub/Sub 实现广播消费
- * 2. 基于 Stream 实现集群消费
- */
-package com.tashow.cloud.mq.redis;
diff --git a/tashow-framework/tashow-framework-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/tashow-framework/tashow-framework-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index ea037a6..7d713e1 100644
--- a/tashow-framework/tashow-framework-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/tashow-framework/tashow-framework-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,3 +1 @@
-com.tashow.cloud.mq.redis.config.RedisMQProducerAutoConfiguration
-com.tashow.cloud.mq.redis.config.RedisMQConsumerAutoConfiguration
com.tashow.cloud.mq.rabbitmq.config.RabbitMQAutoConfiguration
diff --git a/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/idempotent/config/IdempotentConfiguration.java b/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/idempotent/config/IdempotentConfiguration.java
index 784bbad..67effc5 100644
--- a/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/idempotent/config/IdempotentConfiguration.java
+++ b/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/idempotent/config/IdempotentConfiguration.java
@@ -6,14 +6,14 @@ import com.tashow.cloud.protection.idempotent.core.aop.IdempotentAspect;
import com.tashow.cloud.protection.idempotent.core.keyresolver.IdempotentKeyResolver;
import com.tashow.cloud.protection.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
import com.tashow.cloud.protection.idempotent.core.redis.IdempotentRedisDAO;
-import com.tashow.cloud.redis.config.RedisAutoConfiguration;
+import com.tashow.cloud.redis.config.TashowRedisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.List;
-@AutoConfiguration(after = RedisAutoConfiguration.class)
+@AutoConfiguration(after = TashowRedisAutoConfiguration.class)
public class IdempotentConfiguration {
@Bean
diff --git a/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/ratelimiter/config/RateLimiterConfiguration.java b/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/ratelimiter/config/RateLimiterConfiguration.java
index 0ad87a8..b982bf4 100644
--- a/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/ratelimiter/config/RateLimiterConfiguration.java
+++ b/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/ratelimiter/config/RateLimiterConfiguration.java
@@ -3,7 +3,7 @@ package com.tashow.cloud.protection.ratelimiter.config;
import com.tashow.cloud.protection.ratelimiter.core.aop.RateLimiterAspect;
import com.tashow.cloud.protection.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
import com.tashow.cloud.protection.ratelimiter.core.keyresolver.impl.*;
-import com.tashow.cloud.redis.config.RedisAutoConfiguration;
+import com.tashow.cloud.redis.config.TashowRedisAutoConfiguration;
import com.tashow.cloud.protection.ratelimiter.core.redis.RateLimiterRedisDAO;
import org.redisson.api.RedissonClient;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -11,7 +11,7 @@ import org.springframework.context.annotation.Bean;
import java.util.List;
-@AutoConfiguration(after = RedisAutoConfiguration.class)
+@AutoConfiguration(after = TashowRedisAutoConfiguration.class)
public class RateLimiterConfiguration {
@Bean
diff --git a/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/signature/config/ApiSignatureAutoConfiguration.java b/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/signature/config/ApiSignatureAutoConfiguration.java
index fcf1394..dbb4268 100644
--- a/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/signature/config/ApiSignatureAutoConfiguration.java
+++ b/tashow-framework/tashow-framework-protection/src/main/java/com/tashow/cloud/protection/signature/config/ApiSignatureAutoConfiguration.java
@@ -2,7 +2,7 @@ package com.tashow.cloud.protection.signature.config;
import com.tashow.cloud.protection.signature.core.redis.ApiSignatureRedisDAO;
import com.tashow.cloud.protection.signature.core.aop.ApiSignatureAspect;
-import com.tashow.cloud.redis.config.RedisAutoConfiguration;
+import com.tashow.cloud.redis.config.TashowRedisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -12,7 +12,7 @@ import org.springframework.data.redis.core.StringRedisTemplate;
*
* @author Zhougang
*/
-@AutoConfiguration(after = RedisAutoConfiguration.class)
+@AutoConfiguration(after = TashowRedisAutoConfiguration.class)
public class ApiSignatureAutoConfiguration {
@Bean
diff --git a/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/config/TenantAutoConfiguration.java b/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/config/TenantAutoConfiguration.java
index 2771086..6112d02 100644
--- a/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/config/TenantAutoConfiguration.java
+++ b/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/config/TenantAutoConfiguration.java
@@ -1,17 +1,15 @@
package com.tashow.cloud.tenant.config;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.tashow.cloud.common.enums.WebFilterOrderEnum;
import com.tashow.cloud.mybatis.mybatis.core.util.MyBatisUtils;
import com.tashow.cloud.redis.config.TashowCacheProperties;
import com.tashow.cloud.systemapi.api.tenant.TenantApi;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.tashow.cloud.tenant.core.aop.TenantIgnoreAspect;
import com.tashow.cloud.tenant.core.db.TenantDatabaseInterceptor;
import com.tashow.cloud.tenant.core.job.TenantJobAspect;
import com.tashow.cloud.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
-import com.tashow.cloud.tenant.core.mq.redis.TenantRedisMessageInterceptor;
-import com.tashow.cloud.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
import com.tashow.cloud.tenant.core.redis.TenantRedisCacheManager;
import com.tashow.cloud.tenant.core.security.TenantSecurityWebFilter;
import com.tashow.cloud.tenant.core.service.TenantFrameworkService;
@@ -25,7 +23,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.BatchStrategies;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
@@ -97,23 +94,6 @@ public class TenantAutoConfiguration {
return new TenantJobAspect(tenantFrameworkService);
}
- // ========== MQ ==========
-
- /**
- * 多租户 Redis 消息队列的配置类
- *
- * 为什么要单独一个配置类呢?如果直接把 TenantRedisMessageInterceptor Bean 的初始化放外面,会报 RedisMessageInterceptor 类不存在的错误
- */
- @Configuration
- @ConditionalOnClass(name = "com.tashow.cloud.mq.redis.core.RedisMQTemplate")
- public static class TenantRedisMQAutoConfiguration {
-
- @Bean
- public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
- return new TenantRedisMessageInterceptor();
- }
-
- }
@Bean
@ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
@@ -121,12 +101,6 @@ public class TenantAutoConfiguration {
return new TenantRabbitMQInitializer();
}
- @Bean
- @ConditionalOnClass(name = "org.apache.rocketmq.spring.core.RocketMQTemplate")
- public TenantRocketMQInitializer tenantRocketMQInitializer() {
- return new TenantRocketMQInitializer();
- }
-
// ========== Redis ==========
@Bean
diff --git a/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java b/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java
deleted file mode 100644
index 71896db..0000000
--- a/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.tashow.cloud.tenant.core.mq.kafka;
-
-import cn.hutool.core.util.StrUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.env.EnvironmentPostProcessor;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-/**
- * 多租户的 Kafka 的 {@link EnvironmentPostProcessor} 实现类
- *
- * Kafka Producer 发送消息时,增加 {@link TenantKafkaProducerInterceptor} 拦截器
- *
- * @author 芋道源码
- */
-@Slf4j
-public class TenantKafkaEnvironmentPostProcessor implements EnvironmentPostProcessor {
-
- private static final String PROPERTY_KEY_INTERCEPTOR_CLASSES = "spring.kafka.producer.properties.interceptor.classes";
-
- @Override
- public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
- // 添加 TenantKafkaProducerInterceptor 拦截器
- try {
- String value = environment.getProperty(PROPERTY_KEY_INTERCEPTOR_CLASSES);
- if (StrUtil.isEmpty(value)) {
- value = TenantKafkaProducerInterceptor.class.getName();
- } else {
- value += "," + TenantKafkaProducerInterceptor.class.getName();
- }
- environment.getSystemProperties().put(PROPERTY_KEY_INTERCEPTOR_CLASSES, value);
- } catch (NoClassDefFoundError ignore) {
- // 如果触发 NoClassDefFoundError 异常,说明 TenantKafkaProducerInterceptor 类不存在,即没引入 kafka-spring 依赖
- }
- }
-
-}
diff --git a/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java b/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java
deleted file mode 100644
index b55e215..0000000
--- a/tashow-framework/tashow-framework-tenant/src/main/java/com/tashow/cloud/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.tashow.cloud.tenant.core.mq.kafka;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.tashow.cloud.tenant.core.context.TenantContextHolder;
-import org.apache.kafka.clients.producer.ProducerInterceptor;
-import org.apache.kafka.clients.producer.ProducerRecord;
-import org.apache.kafka.clients.producer.RecordMetadata;
-import org.apache.kafka.common.header.Headers;
-import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
-
-import java.util.Map;
-
-import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-
-/**
- * Kafka 消息队列的多租户 {@link ProducerInterceptor} 实现类
- *
- * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
- * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
- *
- * @author 芋道源码
- */
-public class TenantKafkaProducerInterceptor implements ProducerInterceptor