redis 自定义事件监听,支持单机、集群、哨兵 为什么要自定义事件监听呢当然是为了在redis进行某些事件动作的时候增加一些咱们自己的业务逻辑处理比如当key失效的时候处理业务逻辑--支付订单半小时未支付就自动取消订单。这就可以用key失效事件监听来实现。下面就来讲解怎么实现1.首先自定义一个消息工厂此处不要自己再重新获取连接自定义连接池。直接使用redis现有的连接池即可。package com.liu.redisexpired; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import reactor.util.annotation.NonNull; /** * 自定义Redis键空间监听器⼯⼚ * author kevin * date 2022/6/7 */ Slf4j public class RedisMessageListenerFactory implements BeanFactoryAware, ApplicationListenerContextRefreshedEvent { //spring bean工厂 private DefaultListableBeanFactory beanFactory; //redis连接工厂 private RedisConnectionFactory redisConnectionFactory; //redis消息监听 Autowired private MessageListener messageListener; public void setBeanFactory(NonNull BeanFactory beanFactory) { this.beanFactory (DefaultListableBeanFactory) beanFactory; } public void setRedisConnectionFactory(RedisConnectionFactory redisConnectionFactory) { this.redisConnectionFactory redisConnectionFactory; } /** * 自定义事件监听 * author kevin * date 2022/5/27 */ Override public void onApplicationEvent(NonNull ContextRefreshedEvent contextRefreshedEvent) { //定义一个单例bean设置连接工厂为redis的连接工厂然后注册到spring容器 BeanDefinitionBuilder containerBeanDefinitionBuilder BeanDefinitionBuilder .genericBeanDefinition(RedisMessageListenerContainer.class); containerBeanDefinitionBuilder.addPropertyValue(connectionFactory, redisConnectionFactory); containerBeanDefinitionBuilder.setScope(BeanDefinition.SCOPE_SINGLETON); containerBeanDefinitionBuilder.setLazyInit(false); beanFactory.registerBeanDefinition(myRedisKeyListenerContainer, containerBeanDefinitionBuilder.getRawBeanDefinition()); //从spring工厂容器获取消息监听容器配置消息监听器 RedisMessageListenerContainer container beanFactory.getBean(myRedisKeyListenerContainer, RedisMessageListenerContainer.class); //设置监听正则监听节点所有key的所有事件 container.addMessageListener(messageListener, new PatternTopic(__keyevent*__:*)); container.afterPropertiesSet(); //开始监听 container.start(); } }2.将消息工厂注入spring容器在你的redisconfig配置中加入代码主要看最后一个方法package com.liu.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import com.liu.redisexpired.RedisMessageListenerFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; Configuration public class RedisConfig { /** * 配置第一个数据源的RedisTemplate * 注意这里指定使用名称factory 的 RedisConnectionFactory * 并且标识第一个数据源是默认数据源 Primary * author kevin * param redisConnectionFactory : * return org.springframework.data.redis.core.RedisTemplate * date 2022/5/26 */ Bean(redisTemplate) Primary public RedisTemplateString, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) { return getRedisTemplate(redisConnectionFactory); } /** * redis操作工具获取redisTemplate * author kevin * param factory : redis连接工厂 * return org.springframework.data.redis.core.RedisTemplatejava.lang.String,java.lang.Object * date 2022/5/27 12:00 */ private RedisTemplateString, Object getRedisTemplate(RedisConnectionFactory factory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializerObject jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL) //过期方法 om.activateDefaultTyping( LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } /** * 自定义redis消息监听工厂 * author kevin * date 2022/5/27 */ Bean public RedisMessageListenerFactory redisMessageListenerFactory( BeanFactory beanFactory, RedisConnectionFactory redisConnectionFactory) { RedisMessageListenerFactory beans new RedisMessageListenerFactory(); beans.setBeanFactory(beanFactory); beans.setRedisConnectionFactory(redisConnectionFactory); return beans; } }3.编写消息监听编写一个监听器实现MessageListener接口实现onMessage方法得到的message就可以监听所有的key的事件了。此处只监听了key的过期事件然后打印了一句日志如果需要其他操作可直接在此处改写即可package com.liu.redisexpired; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.stereotype.Component; /** * 事件触发监听器 * author kevin * date 2022/5/27 */ Slf4j Component public class KeyEventMessageListener implements MessageListener { /** * 监听获取redis键消息 * author kevin * param message : 事件消息体 * param pattern : 事件监听,消息主题订阅频道如 * __keyevent*__:* 所有key的所有事件 __keyeventa__:* key为a的所有事件 * __keyeventa__:expired key为a的key过期事件 * date 2022/5/27 11:05 */ Override public void onMessage(Message message, byte[] pattern) { //获取redis操作类型: set、expire、expired等操作 String action new String(message.getChannel()); action action.split(:)[1]; //获取redis操作的key String key new String(message.getBody()); //判断失效的key,且是请求限流的key if(expired.equals(action) key.startsWith(request_limit_)){ log.info(监听到的键{},已经失效请求限流已取消, key); } } }此处作者监听的是以request_limit_开头的键失效事件做接口限流的时候顺便整了一下键事件监听。4. 然后验证启动你的项目然后使用你的项目设置一个键并设置失效事件或者直接连接redis命令行先通过如下命令连接redis命令行redis-cli -h 127.0.0.1 -p 6379 -a xxx在命令行中执行命令添加一个键值并设置过期时间为2秒:set request_limit_test 1 PX 2000然后查看项目的控制台是否有对应的输出:以上就是所有内容