spring boot 开启一个监听线程执行任务

本文介绍了一个SpringBoot应用中实现的启动监听器示例。该监听器会在Spring上下文刷新后执行特定任务,例如初始化缓存。通过覆写`onApplicationEvent`方法并在`main`方法中注册监听器来实现。
public class StartApplicationListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
        ApplicationContext parent = applicationContext.getParent();
        if (parent == null) {
            CacheManager cacheManager = applicationContext.getBean(CacheManager.class);
            Cache cache = cacheManager.getCache(MsConstants.NODE_CACHE_NAME);
           new Thread(new Runnable() {
               @Override
               public void run() {
                  //代码
                 
               }
           }).start();
        }
    }

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(FigureServerApplication.class);
    app.addListeners(new StartApplicationListener());
    app.run(args);
}

<think>好的,我现在需要帮助用户在Spring Boot中实现监听特定Redis key过期并发送通知的功能。用户之前已经得到了一些指导,但可能还需要更具体的步骤,特别是如何针对特定的key进行监听。 首先,回顾之前的回答,用户已经了解了如何配置Redis服务器和创建监听器,但之前的示例监听的是所有过期事件。现在用户需要的是只监听特定的key,比如以某个前缀开头的key,比如“ORDER_”。我需要确认如何修改代码来过滤这些特定的key。 接下来,我需要查看用户提供的引用内容。引用[1]中提到了配置RedisMessageListenerContainer并添加消息监听器到特定的PatternTopic,即"__keyevent@*__:expired"。引用[2]也展示了类似的配置,但没有具体说明如何过滤特定key。这可能意味着用户需要自定义监听逻辑,而不是依赖默认的KeyExpirationEventMessageListener。 用户当前的提问是如何监听特定key的过期事件并发送通知。因此,我需要考虑以下步骤: 1. **Redis配置**:确保Redis服务器的键空间通知已启用,配置notify-keyspace-events为Ex,这部分之前已经提到过,需要再次确认。 2. **Spring Boot配置**:创建配置类,定义RedisMessageListenerContainer,并订阅过期事件通道。这部分引用[1]和[2]都有涉及,但可能需要调整监听器。 3. **自定义监听器**:需要创建一个实现MessageListener接口的类,在onMessage方法中处理消息,提取过期的key,并根据特定规则(如key的前缀)过滤事件。然后触发发送通知的逻辑。 4. **发送通知**:根据用户需求,发送通知可能通过邮件、短信、WebSocket等方式实现,这部分需要用户自行实现,但可以给出示例。 需要注意的是,KeyExpirationEventMessageListener默认监听所有数据库的过期事件,而用户需要的是特定key,因此可能需要更底层的处理,比如直接使用MessageListener并检查key是否符合条件。 可能的问题点包括:如何正确配置监听器只处理特定模式的事件。Redis的键空间通知发送的是事件的频道,但key的模式过滤需要在应用层处理,因为Redis的Pub/Sub模式匹配可能不足以精确匹配特定key的前缀,除非使用特定的命名规则和通配符。不过,实际上,过期事件的通知频道是固定的,所以应用层需要在收到事件后自行过滤。 因此,步骤应该是: - 配置RedisMessageListenerContainer,订阅__keyevent@*__:expired频道。 - 创建自定义监听器,实现MessageListener接口。 - 在onMessage方法中解析过期的key,判断是否符合条件(如startsWith("ORDER_"))。 - 如果符合条件,调用发送通知的方法。 另外,需要确保配置类正确地将监听器添加到容器中,并关联到正确的频道。同时,发送通知的具体实现需要用户根据实际情况编写,比如使用Spring的邮件支持或集成消息队列。 可能还需要考虑性能问题,比如高并发下处理大量过期事件时的效率,以及如何避免阻塞监听线程。建议将处理逻辑异步执行,比如使用@Async注解或其他异步机制。 最后,验证步骤:启动应用,设置一个带有特定前缀的key并设置过期时间,观察是否触发通知。如果未触发,检查Redis配置、Spring日志以及监听器是否正确注册。</think>在Spring Boot监听特定Redis Key过期事件并发送通知,需通过**自定义事件过滤+消息通知机制**实现。以下是分步解决方案: --- ### 一、Redis服务端配置(必需) ```conf # redis.conf 启用键空间通知 notify-keyspace-events Ex ``` 验证配置生效: ```bash redis-cli config get notify-keyspace-events # 应返回"Ex" ``` --- ### 二、Spring Boot核心实现 #### 1. 消息监听容器配置 ```java 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.*; @Configuration public class RedisConfig { @Bean public RedisMessageListenerContainer redisContainer( RedisConnectionFactory connectionFactory, CustomKeyExpirationListener listener) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); // 监听所有数据库的key过期事件通道 container.addMessageListener( listener, new PatternTopic("__keyevent@*__:expired") ); return container; } } ``` #### 2. 自定义监听器(核心过滤逻辑) ```java import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.listener.KeyspaceEventMessageListener; import org.springframework.stereotype.Component; @Component public class CustomKeyExpirationListener extends KeyspaceEventMessageListener { public CustomKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) { String expiredKey = message.toString(); // 过滤特定Key(示例:以"ORDER_"开头) if (expiredKey.startsWith("ORDER_")) { sendNotification(expiredKey); } } private void sendNotification(String key) { // 实现通知逻辑(邮件/短信/WebSocket等) System.out.println("发送通知: Key[" + key + "]已过期"); // 示例:调用Spring的邮件服务 // emailService.sendExpirationAlert(key); } } ``` --- ### 三、关键技术原理 1. **事件通道匹配** 通过订阅`__keyevent@*__:expired`模式,监听所有数据库的key过期事件[^1] 2. **过滤机制** 在`onMessage()`中通过字符串匹配(如`startsWith()`/正则表达式)筛选目标Key,过滤效率达$O(1)$[^2] 3. **通知实现** 可集成以下方式: - Spring Mail:发送邮件提醒 - WebSocket:实时推送前端 - MQ(RabbitMQ/Kafka):解耦通知处理 --- ### 四、高级优化方案 #### 1. 提升过滤性能(布隆过滤器) ```java import com.google.common.hash.BloomFilter; // 初始化布隆过滤器 BloomFilter<String> filter = BloomFilter.create( Funnels.stringFunnel(Charset.defaultCharset()), 1000000, // 预期元素数量 0.01 // 误判率 ); // 添加需监听的Key模式 filter.put("ORDER_*"); filter.put("PAYMENT_2023*"); // 在onMessage()中使用 if (filter.mightContain(expiredKey)) { // 进一步精确匹配 } ``` #### 2. 异步处理(防止阻塞) ```java @Async("taskExecutor") public void sendNotification(String key) { // 耗时操作 } ``` 需在启动类添加`@EnableAsync`,并配置线程池[^3] --- ### 五、验证测试 1. 写入测试Key: ```bash redis-cli set ORDER_123 "test" EX 10 # 10秒后过期 ``` 2. 观察控制台输出: ``` 发送通知: Key[ORDER_123]已过期 ``` --- ### 六、常见问题排查 | 问题现象 | 检查点 | |------------------------|--------------------------------| | 未收到通知 | 1. Redis配置`notify-keyspace-events`<br>2. Key命名是否符合过滤规则 | | 高并发下事件丢失 | 1. 增加Redis消息缓冲区大小<br>2. 使用异步队列削峰 | | 通知延迟超过TTL值 | 检查Redis的过期策略是否配置为`volatile-ttl`[^4] | ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值