Springboot整合redis實現(xiàn)發(fā)布訂閱功能介紹步驟
一、redis發(fā)布訂閱簡介
Redis發(fā)布訂閱(pub/sub)是一種消息通信模式:發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收信息。可以參考下面兩張圖進行理解。


二、幾個核心概念解釋
1.頻道
頻道(channel)類似于一個快遞柜,快遞員往里面放快遞,收件人去里面取快遞。管道(channel)是由中間件(redis)提供的,一個redisServer中有多個channel。
2、消息發(fā)布者
可以理解為消息的生產(chǎn)者,消息發(fā)布者通過中間件(redis、mq等)向某個頻道(管道)發(fā)送消息。
3、消息接收者
也可以理解為消息消費者,消息接收者通過訂閱某個頻道(管道)來接收發(fā)布者發(fā)布的消息。
發(fā)布者無需關心是否有人接收消息,發(fā)布者只需要把消息發(fā)布到某個管道中即可;
三、適用場景
1、核心業(yè)務完成后,非核心業(yè)務需要記錄日志,發(fā)郵件,發(fā)短信之類的操作,一般來說,通過這種方式,核心業(yè)務與非核心業(yè)務起到了一個解耦的作用;
2、事件訂閱,比如訂閱UP主,博主相關的消息等;
3、監(jiān)聽事件,比如在分布式微服務場景下,當應用A的某個數(shù)據(jù)發(fā)生變化時,應用B需要同步更新自己的數(shù)據(jù)做自身業(yè)務操作,對于應用A來說并不關心哪個應用,就可以通過這種方式實現(xiàn);
四、與springboot的整合
1、導入基礎依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>2、配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://IP:3306/school?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
username: root
password: root
druid:
max-active: 100
initial-size: 10
max-wait: 60000
min-idle: 5
redis:
host: localhost
port: 6379
cache:
type: redis
3、自定義RedisSubConfig
往容器(RedisMessageListenerContainer)內(nèi)添加消息監(jiān)聽器,注意,container的參數(shù)列表是可以傳多個監(jiān)聽器的,但是要定義監(jiān)聽器的bean。在定義監(jiān)聽器的方法體內(nèi)綁定消息處理器和管道(channel),一個監(jiān)聽器可以監(jiān)聽多個管道,可以通過數(shù)組或者添加多個channel的方式定義;
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.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@Configuration
public class RedisSubConfig {
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory, RedisMessageListener listener) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
//訂閱頻道redis.news 和 redis.life 這個container 可以添加多個 messageListener
container.addMessageListener(listener, new ChannelTopic("redis.user"));
//container.addMessageListener(listener, new ChannelTopic("redis.news"));
return container;
}
}4、自定義消息監(jiān)聽器
需要實現(xiàn)MessageListener 接口,重寫里面的onMessage方法,方法體內(nèi)需要創(chuàng)建一個MessageListenerAdapter(這是一種規(guī)范寫法,用于綁定消息處理器和監(jiān)聽器)。
這種寫法和很多消息中間件對應的API很相似,即通過一個監(jiān)聽的代碼塊來完成監(jiān)聽到消息后具體的業(yè)務操作;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class RedisMessageListener implements MessageListener {
@Autowired
private RedisTemplate redisTemplate;
@Override
public void onMessage(Message message, byte[] pattern) {
// 獲取消息
byte[] messageBody = message.getBody();
// 使用值序列化器轉(zhuǎn)換
Object msg = redisTemplate.getValueSerializer().deserialize(messageBody);
// 獲取監(jiān)聽的頻道
byte[] channelByte = message.getChannel();
// 使用字符串序列化器轉(zhuǎn)換
Object channel = redisTemplate.getStringSerializer().deserialize(channelByte);
// 渠道名稱轉(zhuǎn)換
String patternStr = new String(pattern);
System.out.println(patternStr);
System.out.println("---頻道---: " + channel);
System.out.println("---消息內(nèi)容---: " + msg);
}
}5、redistemplate的序列化
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(mapper);
template.setValueSerializer(jackson2JsonRedisSerializer);
//使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}6、功能測試
下面寫一個測試的接口,模擬業(yè)務處理完畢后,向 redis.user 這個通道發(fā)送一條消息,看看監(jiān)聽器中是否能夠正常接收到消息即可;
@RestController
public class RedisPubController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/getUserById")
public String getUserById(String userId){
//TODO 執(zhí)行主業(yè)務
redisTemplate.convertAndSend("redis.user", userId);
return "hello:" + userId;
}
}啟動工程后調(diào)用接口:
http://localhost:8083/getByUserIdId?userId=1
通過斷點可以觀察發(fā)現(xiàn),通道中的消息被監(jiān)聽器邏輯監(jiān)聽到了,接下來就可以愉快的處理自己的業(yè)務了;

本篇通過案例演示了如何基于springboot整合使用redis的發(fā)布訂閱功能,更多的細節(jié)需要結合實際的開發(fā)場景進行完善
到此這篇關于Springboot整合redis實現(xiàn)發(fā)布訂閱功能介紹步驟的文章就介紹到這了,更多相關Springboot發(fā)布訂閱內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
logback ThrowableProxyConverter類源碼流程解析
這篇文章主要為大家介紹了logback ThrowableProxyConverter類源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12
java實現(xiàn)統(tǒng)計字符串中字符及子字符串個數(shù)的方法示例
這篇文章主要介紹了java實現(xiàn)統(tǒng)計字符串中字符及子字符串個數(shù)的方法,涉及java針對字符串的遍歷、判斷及運算相關操作技巧,需要的朋友可以參考下2017-01-01
java:程序包org.apache.ibatis.annotations不存在報錯解決
這篇文章主要給大家介紹了關于java:程序包org.apache.ibatis.annotations不存在報錯的解決方法,這個錯誤是我在直接導入springboot項目的時候報錯的,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2023-04-04
使用JDBC工具類實現(xiàn)簡單的登錄管理系統(tǒng)
這篇文章主要為大家詳細介紹了使用JDBC工具類實現(xiàn)簡單的登錄管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02

