闲碎记事本 闲碎记事本
首页
  • JAVA
  • Cloudflare
  • 学完再改一遍UI
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

YAN

我要偷偷记录...
首页
  • JAVA
  • Cloudflare
  • 学完再改一遍UI
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • java

  • linux

  • docker

  • redis

    • RedConfig配置
    • Red过期监听
      • 定义RedIs 消息类型
      • 定义消息处理接口
      • 定义消息处理注解 处理对应类型消息
      • 实现处理接口
      • 配置监听类
      • 模拟发布消息
      • 结果打印日志
  • nginx

  • mysql

  • 其他

  • 环境搭建

  • 知识库
  • redis
Yan
2023-03-06
目录

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 执行过期操作
上次更新: 2025/05/22, 07:52:48
RedConfig配置
Nginx 搭建镜像站

← RedConfig配置 Nginx 搭建镜像站→

最近更新
01
Caddy操作指南
04-25
02
虚拟机磁盘扩展
04-22
03
Swap空间
04-22
更多文章>
Theme by Vdoing | Copyright © 2022-2025 YAN | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式