原文链接:
1.SpringBoot Redis监听新增、修改、删除、过期事件(详细)https://blog.csdn.net/Wsl_Cn/article/details/119248995
2.Redis 发布订阅功能在 SpringBoot 中的关键类 https://zhuanlan.zhihu.com/p/59065399
连接redis输入下面命令
#将参数设为字符串"AKE" 表示发送所有类型的通知。
#Ex 过期事件:每当有过期键被删除时发送
#Eg DEL、EXPIRE、RENAME等类型无关的通用命令的通知
config set notify-keyspace-events KEA
#订阅键空间和键事件的主题
psubscribe '__key*__:*'
#重开命令行测试Redis是否正常发送事件
set name wsl
del name
SpringBoot 订阅Redis事件方法一:
1.新增和修改都是set指令,所以监听的主题都一样,实现MessageListener
接口,重写onMessage
这里就是收到消息的处理逻辑,其中pattern为主题String topic = new String(pattern);
@Component
@Data
public class RedisExpiredListener implements MessageListener {
//监听的主题
private final PatternTopic topic = new PatternTopic("__keyevent@*__:set");
/**
*
* @param message 消息
* @param pattern 主题
*/
@Override
public void onMessage(Message message, byte[] pattern) {
String topic = new String(pattern);
String expiredKey = message.toString();
System.out.println("监听到redis过期事件!!!" + expiredKey);
}
}
过期和删除事件举例:
@Component
@Data
public class RedisExpiredListener implements MessageListener {
//监听的主题 Redis最新版7.0.11观察到有时需要使用"__keyevent@*__:expire",重启后变为下面的正常?
private final PatternTopic topic = new PatternTopic("__keyevent@*__:expired");
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
System.out.println("监听到redis过期事件!!!" + expiredKey);
}
}
@Component
@Data
public class RedisDeletedListener implements MessageListener {
//监听的主题
private final PatternTopic topic = new PatternTopic("__keyevent@*__:del");
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
System.out.println("监听到redis删除事件!!!" + expiredKey);
}
}
2.在配置一下MessageListenerContainer
类,将我们写好的监听类添加到该类中即可,删除和过期都是需要添加,我这里就一起添加了后面就不做演示。
@Configuration
public class RedisConfig {
@Autowired
private RedisDeletedListener redisDeletedListener;
@Autowired
private RedisExpiredListener redisExpiredListener;
/**
* SpringBoot整合redis时将缓存数据以json形式存储
*
* @param connectionFactory
* @return
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
Jackson2JsonRedisSerializer<Object> redisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
redisSerializer.setObjectMapper(objectMapper);
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).cacheDefaults(cacheConfiguration).build();
return redisCacheManager;
}
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(connectionFactory);
//监听所有的key的set事件
container.addMessageListener(redisUpdateAndAddListener, redisUpdateAndAddListener.getTopic());
//监听所有key的删除事件
redisMessageListenerContainer.addMessageListener(redisDeletedListener, redisDeletedListener.getTopic());
//监听所有key的过期事件
redisMessageListenerContainer.addMessageListener(redisExpiredListener, redisExpiredListener.getTopic());
return redisMessageListenerContainer;
}
}
方法一完成,进行测试即可
SpringBoot 订阅Redis事件方法二:
1.RedisConfig.java redis配置文件
/**
* SpringCache配置–RedisConfig.java
*
* @author :
*/
@Configuration
public class RedisConfig {
/**
* SpringBoot整合redis时将缓存数据以json形式存储
*
* @param connectionFactory
* @return
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
Jackson2JsonRedisSerializer<Object> redisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
redisSerializer.setObjectMapper(objectMapper);
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).cacheDefaults(cacheConfiguration).build();
return redisCacheManager;
}
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(connectionFactory);
return redisMessageListenerContainer;
}
}
2.订阅删除
KeyDeleteEventMessageListener.java
package com.xf.listener;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisKeyExpiredEvent;
import org.springframework.data.redis.listener.KeyspaceEventMessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.lang.Nullable;
public class KeyDeleteEventMessageListener extends KeyspaceEventMessageListener implements ApplicationEventPublisherAware {
private static final Topic KEYEVENT_DELETE_TOPIC = new PatternTopic("__keyevent@*__:del");
@Nullable
private ApplicationEventPublisher publisher;
public KeyDeleteEventMessageListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/**
*注意这里将listener和Topic注册到Container中
**/
protected void doRegister(RedisMessageListenerContainer listenerContainer) {
listenerContainer.addMessageListener(this, KEYEVENT_DELETE_TOPIC);
}
protected void doHandleMessage(Message message) {
this.publishEvent(new RedisKeyExpiredEvent(message.getBody()));
}
protected void publishEvent(RedisKeyExpiredEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
}
RedisDeletedListener.java
package com.xf.listener;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* @author xiongfeng
* @date 2023/5/18
*/
@Component
public class RedisDeletedListener extends KeyDeleteEventMessageListener {
public RedisDeletedListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
System.out.println("监听到redis删除事件!!!" + expiredKey);
}
}
3.订阅过期事件同样新建KeyExpirationEventMessageListener.java 和 RedisExpiredListener.java 两个类
其中KeyExpirationEventMessageListener.java类Spring自带可以不新建,KEYEVENT_DELETE_TOPIC 需改为下述值,订阅其他事件同理
private static final Topic KEYEVENT_DELETE_TOPIC = new PatternTopic("__keyevent@*__:expired");