Red过期监听
# Redis过期事件监听
# 定义RedIs 消息类型
/**
* 发布类型
*/
@Getter
@AllArgsConstructor
public enum PubType {
/**
* 发布计划
* 此次测试使用 需要新增通知类型需要自行添加
*/
PLAN("pub:plan"),
/**
* 到期通知
* 此次测试使用 需要新增通知类型需要自行添加
*/
EXPIRED_NOTICE("expired:notice"),
//.....
;
private final String prefix;
/**
* 通过数据唯一标识生成 发布key
* @param unique 数据唯一标识
* @return 发布key
*/
public String getKey(String unique){
return String.format("%s:%s",this.prefix,unique);
}
/**
* 得到发布key唯一标识
* @param key 发布key
* @return 通过发布key 解析出来的标识
*/
public static String getUnique(String key){
return key.substring(key.lastIndexOf(":")+1);
}
/**
* 得到发布类型 使用结果需要判空
* @param key 发布key
* @return 通过发布key 解析出来的类型
*/
public static PubType getPubType(String key){
String prefix = key.substring(0, key.lastIndexOf(":"));
for (PubType value : PubType.values()) {
if(!value.getPrefix().equals(prefix)){
continue;
}
return value;
}
return null;
}
/**
* 发布
* @param unique 发布唯一标识
* @param timeout timeout 秒后过期
*/
public void pub(final String unique,Integer timeout) {
new IRedisMessage() {}.pub(this,unique,timeout);
}
}
# 定义消息处理接口
public interface IRedisMessage {
/**
* 发布
* @param pubType 发布类型
* @param unique 发布唯一标识
* @param timeout timeout 秒后过期
*/
default void pub(PubType pubType, String unique,Integer timeout){
RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
if(ObjectUtils.isEmpty(redisCache)){
throw new ServiceException("redisCache not found");
}
redisCache.setCacheObject(pubType.getKey(unique),unique,timeout,TimeUnit.SECONDS);
}
/**
* 接受到通知开始执行
* @param key 数据唯一标识
*/
default void exec(String key){}
}
# 定义消息处理注解 处理对应类型消息
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisMessage {
/**
* 标准发布类型
* @return 发布类型
*/
PubType value();
}
# 实现处理接口
@Slf4j
@RedisMessage(PubType.PLAN)
@Component
public class PlanRedisHandler implements IRedisMessage {
@Override
public void exec(String key) {
log.info("类型:{},唯一标识:{} 执行过期操作",PubType.PLAN,key);
}
}
# 配置监听类
@Slf4j
@Configuration
public class RedisPushSubConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
@Component
public static class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
// 过期key
String expiredKey = message.toString();
PubType pubType = PubType.getPubType(expiredKey);
log.warn("key:{} 过期了!!! 类型:{},数据标识:{}",expiredKey,PubType.getUnique(expiredKey),PubType.getPubType(expiredKey));
// 下面可以通过redis工具获取值或者执行业务逻辑
if(null == pubType){
return;
}
Map<String, IRedisMessage> redisMessageBeanMap = SpringUtils.getBeansOfType(IRedisMessage.class);
for (Map.Entry<String, IRedisMessage> entry : redisMessageBeanMap.entrySet()) {
RedisMessage annotation = entry.getValue().getClass().getAnnotation(RedisMessage.class);
if(null == annotation ){
continue;
}
if( !annotation.value().equals(pubType)){
continue;
}
entry.getValue().exec(expiredKey);
}
}
public RedisKeyExpirationListener(RedisMessageListenerContainer redisMessageListenerContainer ){
super(redisMessageListenerContainer);
}
}
}
import java.util.Map;
@Slf4j
@Configuration
public class RedisPushSubConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
@Component
public static class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
// 过期key
String expiredKey = message.toString();
PubType pubType = PubType.getPubType(expiredKey);
log.warn("key:{} 过期了!!! 类型:{},数据标识:{}",expiredKey,PubType.getUnique(expiredKey),PubType.getPubType(expiredKey));
// 下面可以通过redis工具获取值或者执行业务逻辑
if(null == pubType){
return;
}
Map<String, IRedisMessage> redisMessageBeanMap = SpringUtils.getBeansOfType(IRedisMessage.class);
for (Map.Entry<String, IRedisMessage> entry : redisMessageBeanMap.entrySet()) {
RedisMessage annotation = entry.getValue().getClass().getAnnotation(RedisMessage.class);
if(null == annotation ){
continue;
}
if( !annotation.value().equals(pubType)){
continue;
}
entry.getValue().exec(expiredKey);
}
}
public RedisKeyExpirationListener(RedisMessageListenerContainer redisMessageListenerContainer ){
super(redisMessageListenerContainer);
}
}
}
# 模拟发布消息
@PostMapping("/pub")
public void pub(@RequestParam("key")String key) {
PubType.PLAN.pub(key,10);
}
# 结果打印日志
push后10秒触发过期通知
18:08:36.175 [http-nio-8080-exec-1] INFO c.y.f.f.PageRequestFilter - [doFilterInternal,21] - 当前请求方式:[POST]>>路径:/app/test/pub
18:08:46.660 [container-2] WARN c.y.c.c.r.c.RedisPushSubConfig - [onMessage,41] - key:pub:plan:111111 过期了!!! 类型:111111,数据标识:PLAN
18:08:46.670 [container-2] INFO c.y.s.h.r.PlanRedisHandler - [exec,16] - 类型:PLAN,唯一标识:pub:plan:111111 执行过期操作
上次更新: 2024/11/05, 08:29:31