Springboot整合redis實(shí)現(xiàn)發(fā)布訂閱功能介紹步驟
一、redis發(fā)布訂閱簡介
Redis發(fā)布訂閱(pub/sub)是一種消息通信模式:發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收信息??梢詤⒖枷旅鎯蓮垐D進(jìn)行理解。
二、幾個(gè)核心概念解釋
1.頻道
頻道(channel)類似于一個(gè)快遞柜,快遞員往里面放快遞,收件人去里面取快遞。管道(channel)是由中間件(redis)提供的,一個(gè)redisServer中有多個(gè)channel。
2、消息發(fā)布者
可以理解為消息的生產(chǎn)者,消息發(fā)布者通過中間件(redis、mq等)向某個(gè)頻道(管道)發(fā)送消息。
3、消息接收者
也可以理解為消息消費(fèi)者,消息接收者通過訂閱某個(gè)頻道(管道)來接收發(fā)布者發(fā)布的消息。
發(fā)布者無需關(guān)心是否有人接收消息,發(fā)布者只需要把消息發(fā)布到某個(gè)管道中即可;
三、適用場景
1、核心業(yè)務(wù)完成后,非核心業(yè)務(wù)需要記錄日志,發(fā)郵件,發(fā)短信之類的操作,一般來說,通過這種方式,核心業(yè)務(wù)與非核心業(yè)務(wù)起到了一個(gè)解耦的作用;
2、事件訂閱,比如訂閱UP主,博主相關(guān)的消息等;
3、監(jiān)聽事件,比如在分布式微服務(wù)場景下,當(dāng)應(yīng)用A的某個(gè)數(shù)據(jù)發(fā)生變化時(shí),應(yīng)用B需要同步更新自己的數(shù)據(jù)做自身業(yè)務(wù)操作,對于應(yīng)用A來說并不關(guān)心哪個(gè)應(yīng)用,就可以通過這種方式實(shí)現(xiàn);
四、與springboot的整合
1、導(dǎo)入基礎(chǔ)依賴
<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ù)列表是可以傳多個(gè)監(jiān)聽器的,但是要定義監(jiān)聽器的bean。在定義監(jiān)聽器的方法體內(nèi)綁定消息處理器和管道(channel),一個(gè)監(jiān)聽器可以監(jiān)聽多個(gè)管道,可以通過數(shù)組或者添加多個(gè)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 這個(gè)container 可以添加多個(gè) messageListener container.addMessageListener(listener, new ChannelTopic("redis.user")); //container.addMessageListener(listener, new ChannelTopic("redis.news")); return container; } }
4、自定義消息監(jiān)聽器
需要實(shí)現(xiàn)MessageListener 接口,重寫里面的onMessage方法,方法體內(nèi)需要?jiǎng)?chuàng)建一個(gè)MessageListenerAdapter(這是一種規(guī)范寫法,用于綁定消息處理器和監(jiān)聽器)。
這種寫法和很多消息中間件對應(yīng)的API很相似,即通過一個(gè)監(jiān)聽的代碼塊來完成監(jiān)聽到消息后具體的業(yè)務(wù)操作;
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、功能測試
下面寫一個(gè)測試的接口,模擬業(yè)務(wù)處理完畢后,向 redis.user 這個(gè)通道發(fā)送一條消息,看看監(jiān)聽器中是否能夠正常接收到消息即可;
@RestController public class RedisPubController { @Autowired private RedisTemplate redisTemplate; @GetMapping("/getUserById") public String getUserById(String userId){ //TODO 執(zhí)行主業(yè)務(wù) redisTemplate.convertAndSend("redis.user", userId); return "hello:" + userId; } }
啟動工程后調(diào)用接口:
http://localhost:8083/getByUserIdId?userId=1
通過斷點(diǎn)可以觀察發(fā)現(xiàn),通道中的消息被監(jiān)聽器邏輯監(jiān)聽到了,接下來就可以愉快的處理自己的業(yè)務(wù)了;
本篇通過案例演示了如何基于springboot整合使用redis的發(fā)布訂閱功能,更多的細(xì)節(jié)需要結(jié)合實(shí)際的開發(fā)場景進(jìn)行完善
到此這篇關(guān)于Springboot整合redis實(shí)現(xiàn)發(fā)布訂閱功能介紹步驟的文章就介紹到這了,更多相關(guān)Springboot發(fā)布訂閱內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
logback ThrowableProxyConverter類源碼流程解析
這篇文章主要為大家介紹了logback ThrowableProxyConverter類源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12java實(shí)現(xiàn)統(tǒng)計(jì)字符串中字符及子字符串個(gè)數(shù)的方法示例
這篇文章主要介紹了java實(shí)現(xiàn)統(tǒng)計(jì)字符串中字符及子字符串個(gè)數(shù)的方法,涉及java針對字符串的遍歷、判斷及運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-01-01java:程序包org.apache.ibatis.annotations不存在報(bào)錯(cuò)解決
這篇文章主要給大家介紹了關(guān)于java:程序包org.apache.ibatis.annotations不存在報(bào)錯(cuò)的解決方法,這個(gè)錯(cuò)誤是我在直接導(dǎo)入springboot項(xiàng)目的時(shí)候報(bào)錯(cuò)的,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04使用JDBC工具類實(shí)現(xiàn)簡單的登錄管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了使用JDBC工具類實(shí)現(xiàn)簡單的登錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02Java基礎(chǔ)之創(chuàng)建虛擬機(jī)對象的過程詳細(xì)總結(jié)
本文基于虛擬機(jī)HotSpot和常用的內(nèi)存區(qū)域Java堆深入對象分配、布局和訪問的全過程,文中有非常詳細(xì)的圖文解說,對正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05