在 Spring Boot 中实现 Redis 队列的“监听”效果,常用做法是:
- 使用 **线程/异步任务** 持续阻塞式(`BLPOP`)监听 Redis 列表,当有消息时立即消费。
- 或者利用 Spring Data Redis 的消息监听器(`RedisMessageListenerContainer`)配合 Redis 的发布订阅(Pub/Sub)机制,但这不是真正的队列监听,适合广播订阅场景。
---
### 重点说明
- Redis 列表队列用 `BLPOP` 阻塞弹出操作实现监听效果,消费者线程持续等待,有消息立即返回处理。
- Spring Boot 不自带对 `BLPOP` 的自动监听支持,需要手动写线程或异步任务执行循环阻塞消费。
---
## 方案示例:基于 `BLPOP` 的阻塞监听
### 1. 编写服务类,持续监听并处理消息
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class RedisQueueListener {
private static final String QUEUE_KEY = "myQueue";
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 启动监听线程,持续阻塞监听队列
*/
@PostConstruct
public void startListener() {
Thread thread = new Thread(() -> {
while (true) {
try {
// 阻塞弹出消息,超时时间为0,表示无限等待
String message = redisTemplate.opsForList().rightPop(QUEUE_KEY, 0);
if (message != null) {
// 消息处理逻辑
System.out.println("收到消息:" + message);
// 这里可以调用业务处理方法
}
} catch (Exception e) {
e.printStackTrace();
// 发生异常时休眠几秒,防止死循环
try {
Thread.sleep(3000);
} catch (InterruptedException ignored) {}
}
}
});
thread.setDaemon(true); // 守护线程,随应用关闭
thread.start();
}
}
```
### 2. 说明
- `@PostConstruct` 注解保证应用启动时启动监听线程
- 该线程调用 `rightPop` 阻塞版本(带超时0秒表示无限阻塞)
- 有消息时立即返回并打印/处理,没消息时线程处于阻塞等待状态,不会占用 CPU
- 异常捕获防止线程意外死亡
---
## 方案2:基于 Spring 的线程池和异步任务
如果项目已经启用异步支持,也可以用异步线程池执行监听任务:
```java
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class RedisQueueListenerAsync {
@Async
@PostConstruct
public void listen() {
while (true) {
try {
String msg = ...; // 调用带阻塞的 rightPop
if (msg != null) {
System.out.println("监听消费消息:" + msg);
}
} catch (Exception e) {
e.printStackTrace();
Thread.sleep(3000);
}
}
}
}
```
注意要在启动类加上 `@EnableAsync`。
---
## 方案3:Redis 发布订阅监听(适合广播消息,不是队列)
此外,Redis 支持发布订阅机制:
```java
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new ChannelTopic("topicName"));
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter(MessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
@Service
public class MessageSubscriber {
public void onMessage(String message, String pattern) {
System.out.println("接收到消息:" + message);
}
}
```
这种机制没有排队消费功能,消息发布立即广播给所有订阅者。适合事件通知、广播,不适合精确排队消费。
---
## 总结
| 方案 | 适用场景 | 说明 |
|----------------------------|-------------------|-----------------------------------|
| Redis 阻塞列表监听(BLPOP) | 队列消息消费 | 阻塞等待消息,适合生产者-消费者模式 |
| Redis 发布订阅机制(Pub/Sub)| 消息广播/通知 | 消息广播给多个订阅者,不支持排队 |
---
如果您需要我可以帮您写完整的线程池版本、集成示例代码,或者帮您用 Redisson 框架做分布式队列监听示例,欢迎告诉我!