Springboot使用redisson?+?自定義注解實現消息的發(fā)布訂閱(解決方案)
前言
在一些小型場景下,使用mq中間件可能會為原有項目增加不少維護成本,使用redisson實現消息的收發(fā)是個不錯的選擇
什么是redisson?
官網:Redisson: Easy Redis Java client with features of In-Memory Data Grid
Redisson是一個基于Redis的Java駐留內存數據網格(In-Memory Data Grid)和分布式鎖框架。它提供了一系列的分布式Java對象和服務,可以幫助開發(fā)者更方便地使用Redis作為數據存儲和分布式鎖的解決方案。

Redisson的主要功能包括:
- 分布式集合:Redisson提供了分布式的Set、List、Queue、Deque等集合,可以在分布式環(huán)境下進行操作,實現數據共享和協(xié)作。
- 分布式映射:Redisson提供了分布式的Map、Multimap、ConcurrentMap等映射結構,可以在分布式環(huán)境下進行操作,實現數據的存儲和共享。
- 分布式鎖:Redisson提供了可重入鎖、公平鎖、讀寫鎖等分布式鎖,可以在分布式環(huán)境下實現資源的互斥訪問,保證數據的一致性和并發(fā)安全。
- 分布式對象:Redisson提供了分布式的AtomicLong、CountDownLatch、Semaphore等對象,可以在分布式環(huán)境下實現共享狀態(tài)和協(xié)作操作。
Redisson的使用場景包括但不限于:
分布式緩存:Redisson可以作為分布式緩存的解決方案,將數據存儲在Redis中,提高數據的讀取速度和系統(tǒng)的性能。
分布式鎖:Redisson可以用于實現分布式鎖,保證在分布式環(huán)境下對共享資源的互斥訪問,避免數據的并發(fā)沖突。
分布式任務調度:Redisson可以用于實現分布式任務調度,將任務分發(fā)到不同的節(jié)點上執(zhí)行,提高系統(tǒng)的并發(fā)處理能力。
Redisson的優(yōu)點包括:
簡單易用:Redisson提供了簡潔的API和豐富的文檔,使得使用者可以快速上手。
高性能:Redisson利用Redis的高性能特性,可以實現快速的數據讀寫和并發(fā)操作。
可靠性:Redisson提供了分布式鎖和數據持久化等機制,保證數據的一致性和可靠性。
Redisson的缺點包括:
依賴于Redis:Redisson需要依賴Redis作為數據存儲和分布式鎖的后端,需要確保Redis的可用性和性能。
部署復雜性:Redisson的部署和配置相對復雜,需要對Redis和Redisson的相關參數進行調優(yōu)和配置。
redisson發(fā)布訂閱的基本使用
// 創(chuàng)建Redisson客戶端
RedissonClient redisson = Redisson.create();
// 獲取RTopic對象
RTopic<String> topic = redisson.getTopic("myTopic");
// 發(fā)布消息
topic.publish("Hello, Redisson!");
// 添加監(jiān)聽器
topic.addListener(String.class, (channel, msg) -> {
System.out.println("Received message: " + msg);
});
// 關閉Redisson客戶端
redisson.shutdown();發(fā)布和訂閱,是我們需要對同一個 Topic 進行發(fā)布和監(jiān)聽操作。但這個操作的代碼是一種手動編碼,但在我們實際使用中,如果所有的都是手動編碼,一個是非常麻煩,再有一個是非常累人。通過自定義注解,來完成動態(tài)監(jiān)聽和將對象動態(tài)注入到 Spring 容器中,讓需要注入的屬性,可以被動態(tài)注入。
結合自定義注解優(yōu)雅實現
導入依賴
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.14.1</version>
</dependency>編寫redisson初始化配置
redis:
sdk:
config:
host: localhost
port: 6379
pool-size: 10
min-idle-size: 5
idle-timeout: 30000
connect-timeout: 5000
retry-attempts: 3
retry-interval: 1000
ping-interval: 60000
keep-alive: true編寫redisson配置類
/**
* @description redis連接配置
* @create 2023/12/17 20:48:13
*/
@Data
@ConfigurationProperties(prefix = "redis.sdk.config", ignoreInvalidFields = true)
public class RedissonCientConfigProperties {
/** host:ip */
private String host;
/** 端口 */
private int port;
/** 賬密 */
private String password;
/** 設置連接池的大小,默認為64 */
private int poolSize = 64;
/** 設置連接池的最小空閑連接數,默認為10 */
private int minIdleSize = 10;
/** 設置連接的最大空閑時間(單位:毫秒),超過該時間的空閑連接將被關閉,默認為10000 */
private int idleTimeout = 10000;
/** 設置連接超時時間(單位:毫秒),默認為10000 */
private int connectTimeout = 10000;
/** 設置連接重試次數,默認為3 */
private int retryAttempts = 3;
/** 設置連接重試的間隔時間(單位:毫秒),默認為1000 */
private int retryInterval = 1000;
/** 設置定期檢查連接是否可用的時間間隔(單位:毫秒),默認為0,表示不進行定期檢查 */
private int pingInterval = 0;
/** 設置是否保持長連接,默認為true */
private boolean keepAlive = true;
}編寫自定義主題注解,用來指定主題
/**
* @description redisson 消息主題注解
* @create 2023/12/17 21:56:10
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
public @interface RedisTopic {
// 主題名稱
String topic() default "";
}初始化Redisson客戶端,注冊主題監(jiān)聽
/**
* @description redis客戶端
* @create 2023/12/17 20:49:41
*/
@Configuration
@EnableConfigurationProperties(RedisCientConfigProperties.class)
public class RedisClientConfig {
public RedissonClient redissonClient(ConfigurableApplicationContext applicationContext, RedisCientConfigProperties properties) {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://" + properties.getHost() + ":" + properties.getPort())
.setPassword(properties.getPassword())
.setConnectionPoolSize(properties.getPoolSize())
.setConnectionMinimumIdleSize(properties.getMinIdleSize())
.setIdleConnectionTimeout(properties.getIdleTimeout())
.setConnectTimeout(properties.getConnectTimeout())
.setRetryAttempts(properties.getRetryAttempts())
.setRetryInterval(properties.getRetryInterval())
.setPingConnectionInterval(properties.getPingInterval())
.setKeepAlive(properties.isKeepAlive())
;
RedissonClient redissonClient = Redisson.create(config);
// 注冊消息發(fā)布訂閱主題Topic
// 找到所有實現了Redisson中MessageListener接口的bean名字
String[] beanNamesForType = applicationContext.getBeanNamesForType(MessageListener.class);
for (String beanName : beanNamesForType) {
// 通過bean名字獲取到監(jiān)聽bean
MessageListener bean = applicationContext.getBean(beanName, MessageListener.class);
Class<? extends MessageListener> beanClass = bean.getClass();
// 如果bean的注解里包含我們的自定義注解RedisTopic.class,則以RedisTopic注解的值作為name將該bean注冊到bean工廠,方便在別處注入
if (beanClass.isAnnotationPresent(RedisTopic.class)) {
RedisTopic redisTopic = beanClass.getAnnotation(RedisTopic.class);
RTopic topic = redissonClient.getTopic(redisTopic.topic());
topic.addListener(String.class, bean);
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
beanFactory.registerSingleton(redisTopic.topic(), topic);
}
}
return redissonClient;
}
}在監(jiān)聽器上聲明注解,如下服務即訂閱了testRedisTopic02主題
@Slf4j
@Service
@RedisTopic(topic = "testRedisTopic02")
public class RedisTopicListener02 implements MessageListener<String> {
@Override
public void onMessage(CharSequence channel, String msg) {
log.info("02-監(jiān)聽消息(Redis 發(fā)布/訂閱): {}", msg);
}
}使用,發(fā)布消息
@Slf4j
@Repository
public class OrderRepository implements IOrderRepository {
@Resource(name = "testRedisTopic02")
private RTopic testRedisTopic02;
@Resource(name = "testRedisTopic03")
private RTopic testRedisTopic03;
@Override
public String createOrder(OrderAggregate orderAggregate) {
// 向 testRedisTopic02 發(fā)布消息
testRedisTopic02.publish(JSON.toJSONString(orderEntity));
// 向 testRedisTopic03 發(fā)布消息
testRedisTopic03.publish(JSON.toJSONString(orderEntity));
return orderId;
}
} 到此這篇關于Springboot中使用redisson + 自定義注解優(yōu)雅的實現消息的發(fā)布訂閱的文章就介紹到這了,更多相關Springboot中使用redisson + 自定義注解優(yōu)雅的實現消息的發(fā)布訂閱內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mybatis中<if>標簽bool值類型為false判斷方法
這篇文章主要給大家介紹了關于mybatis中<if>標簽bool值類型為false判斷方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用mybatis具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-08-08
Easyui的combobox實現動態(tài)數據級聯(lián)效果
這篇文章主要介紹了Easyui的combobox實現動態(tài)數據級聯(lián)效果的相關資料,感興趣的小伙伴們可以參考一下2016-06-06

