在实际的开发项目中,监听 key 的过期事件,应用非常广泛,例如:优惠券过期,处理各种超时事件等等
先贴出SpringBoot工程结构
实现步骤:
1.修改Redis配置文件
找到 redis.windows.conf或redis.conf 文件,搜索 “notify-keyspace-events”找到原本的notify-keyspace-events " ",修改为 “notify-keyspace-events Ex”,这样我们的 Redis 就支持 key 过期事件的监听了
2.添加依赖
<!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.0.0</version> </dependency>
3.配置yml
spring: application: name: Redis redis: host: 127.0.0.1 port: 6379
4.创建监听类
package com.zk.redis.redisTimeoutEvent; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.stereotype.Component; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; @Slf4j @Component public class KeyExpiredListener extends KeyExpirationEventMessageListener { @Autowired public RedisTemplate<String,String> redisTemplate; public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] bytes) { //获取失效key名称 String expireKey = new String(message.getBody(), StandardCharsets.UTF_8); //获取key原本的value 获取不到 是null String expireKeyValue = redisTemplate.opsForValue().get("myKey"); log.info("expireKey---"+expireKey); log.info("expireKeyValue---"+expireKeyValue); } }
5.创建一个配置类RedisListenerConfig
package com.zk.redis.redisTimeoutEvent; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.RedisMessageListenerContainer; @Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
6.写一个Controller测试一下
package com.zk.redis.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @RestController public class RedisController { @Autowired public RedisTemplate<String,String> redisTemplate; @RequestMapping(value = "/redisTest", method = RequestMethod.GET, produces = "application/json;charset=UTF-8") public Map<String,Object> redisTest(){ //redis中存入5秒失效的key redisTemplate.opsForValue().set("myKey", "myValue",5, TimeUnit.SECONDS); String myKey = redisTemplate.opsForValue().get("myKey"); Map<String,Object> resultMap = new HashMap<String,Object>(); resultMap.put("myKey",myKey); return resultMap; } }
7.项目运行后,浏览器输入访问地址,输出结果,说明key失效后触发onMessage().
上图说明成功监听并触发事件.