命令行使用发布订阅:

springboot使用发布订阅
redisTemplate.convertAndSend(channel名字,数据)
springboot中监听redis发布的内容,,有两种方式:
- 实现MessageListener类
java
/**
* 实现接口 消费
*/
@Component
public class MyConsumer01 implements MessageListener {
@Autowired
RedisTemplate redisTemplate;
@Override
public void onMessage(Message message, byte[] pattern) {
// 消息的内容
byte[] body = message.getBody();
String s = new String(body);
// 用默认的序列化器,,序列化
Book book = (Book) redisTemplate.getValueSerializer().deserialize(body);
System.out.println("book = " + book);
System.out.println("s = " + s);
}
}
- 自定义类,,因为是自定义的类,,所以需要一个适配器把他转换成 MessageListener 才能使用
java
@Component
public class MyConsumer02 {
/**
* 这个方法你想怎么写怎么写,,但是需要配置注册进去 ===》 通过一个适配器,,去适配
* @param message
* @param channel
*/
public void receiveMessage(Book message, String channel){
System.out.println("message = " + message);
}
}
这个自定义的监听器需要通过适配器适配:
java
/**
* 给自定义的 MyConsumer02 来适配
* @return
*/
@Bean
MessageListenerAdapter messageListenerAdapter(){
// 告诉他 接收消息的方法
MessageListenerAdapter receiveMessage = new MessageListenerAdapter(myConsumer02, "receiveMessage");
// 这个反序列化不会平白无故的转成 想要的类型 ===> 设置反序列化方式
// 将来收到消息之后,,会通过这里设置的序列化方案,,进行反序列化
receiveMessage.setSerializer(new GenericJackson2JsonRedisSerializer());
return receiveMessage;
}
想让这两个监听器生效,,还需要配置监听器,,设置这两个监听器,,去监听,,哪些通道:
java
@Bean
RedisMessageListenerContainer container(MyConsumer01 myConsumer01, MessageListenerAdapter messageListenerAdapter, RedisConnectionFactory redisConnectionFactory){
// 注册监听器
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(myConsumer01,new ChannelTopic(CHANNEL_01));
container.addMessageListener(messageListenerAdapter,new PatternTopic(CHANNEL_02));
return container;
}
收发对象可以定义序列化方案,,, 对象的序列化和反序列化,,一般都用GenericJackson2JsonRedisSerializer
java
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
redisTemplate 里面有方法能直接处理二进制,,redisTemplate.getValueSerializer().deserialize(body); 可以直接将二进制按照 value的序列化器去 序列化
队列
redis中list可以做队列,,它里面有block开头的,,,阻塞队列,,,阻塞多少时间才去执行,,,
list做队列,,必须自己去通过死循环,,或者定时器,,去拉取list中的内容,,,, 他没有自己的监听器,,没法监听,,,
但是list中有一种阻塞队列,,,就是阻塞多少时间,,如果这个时间到了,,才放弃阻塞,,,这就能避免无限空死循环,,,
java
package com.cj.pub_sub_demo.consumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class MyConsumerList01 {
@Autowired
StringRedisTemplate redisTemplate;
public void receive(){
while (true){
// 延迟获取消息
String o = (String) redisTemplate.opsForList().rightPop("list_mq",10, TimeUnit.SECONDS);
if (o != null){
System.out.println("收到消息 = " + o);
}else{
System.out.println("111");
}
}
}
public void blockReceive() throws InterruptedException {
// bound 之后不用绑定key
BoundListOperations listMq = redisTemplate.boundListOps("list_mq");
// 接下来都是绑定key的
while (true){
Object o = listMq.rightPop();
if (o != null){
System.out.println(o);
}else{
Thread.sleep(1000);
}
}
}
}
这个队列,可以在springboot刚启动的时候,就开启这个死循环:
java
/**
* 1. 数据预加载 : 在启动时向数据库插入默认数据,配置信息,,或者测试数据
* 2. 缓存预热 :从数据库加载热点数据到redis缓存中
* 3. 资源检查: 验证外部服务,,如邮件服务器,文件存储是否可用
* 4. 执行命令行逻辑: 对于非web应用,,如批处理任务,,在这里编写主要的业务逻辑
* 5. 发送启动通知,通知监控系统或日志系统 已启动成功
*/
@Component
public class MyCommandRunner implements CommandLineRunner {
@Autowired
MyConsumerList01 myConsumerList01;
@Override
public void run(String... args) throws Exception {
myConsumerList01.receive();
}
}