解決spring集成redisson踩過的坑
spring集成redisson踩過的坑
我用spring的xml集成一直報錯,所以只能選擇注解方式:
@Configuration
public class RedissionConfig {
Logger log = LoggerFactory.getLogger(RedissionConfig.class);
@Value("${redis_ip}")
String redis_ip;
@Value("${redis_port}")
String redis_port;
@Value("${redis_password}")
String redis_password;
@Bean(name="redissonClient")
public RedissonClient init(){
log.info("redis_ip:"+redis_ip);
log.info("redis_port:" +redis_port);
log.info("redis_password:"+redis_password);
Config config = new Config();
String url = "redis://"+redis_ip+":"+redis_port;
log.info(url);
config.useSingleServer().setAddress(url).setPassword(redis_password);
RedissonClient redissonClient = Redisson.create(config);
log.info("初始化RedissonClient");
return redissonClient;
}
}
第一坑就是版本兼容問題
我用的Spring是4.2.7,第一次集成的是3.12.0,會報以下錯誤:
嚴重: Unable to process Jar entry [module-info.class] from Jar [jar:file:/C:/Users/Administrator/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.10.1/jackson-dataformat-yaml-2.10.1.jar!/] for annotations org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19 at org.apache.tomcat.util.bcel.classfile.Constant.readConstant(Constant.java:133) at org.apache.tomcat.util.bcel.classfile.ConstantPool.<init>(ConstantPool.java:60) at org.apache.tomcat.util.bcel.classfile.ClassParser.readConstantPool(ClassParser.java:209) at org.apache.tomcat.util.bcel.classfile.ClassParser.parse(ClassParser.java:119) at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2134) at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:2010) at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1976) at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1961) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1319) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:878) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:376) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5322) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) at java.util.concurrent.FutureTask.run(FutureTask.java) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:748)
所以把版本降低到3.10.0,就不會報錯了。
第二個坑是設(shè)置密碼問題
因為要區(qū)分多環(huán)境,所以把redis的信息寫到配置文件中,如果按照上面的配置,會報以下錯誤:
Caused by: org.redisson.client.RedisException: ERR Client sent AUTH, but no password is set. channel: [id: 0xe37c85e0, L:/192.168.0.128:54867 - R:192.168.0.128/192.168.0.128:5802] command: (AUTH), params: [] at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:314) at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:130) at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:110) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502) at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:656) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:591) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:508) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:470) ... 3 more
所以要判斷密碼是否為空,如果是空不做參數(shù)即可,下面是改正過的代碼:
public RedissonClient init(){
log.info("redis_ip:"+redis_ip);
log.info("redis_port:" +redis_port);
log.info("redis_password:"+redis_password);
Config config = new Config();
String url = "redis://"+redis_ip+":"+redis_port;
log.info(url);
SingleServerConfig singleServerConfig = config.useSingleServer().setAddress(url);
if(!StringUtils.isEmpty(redis_password)){
singleServerConfig.setPassword(redis_password);
}
RedissonClient redissonClient = Redisson.create(config);
log.info("初始化RedissonClient");
return redissonClient;
}
另外,網(wǎng)上的帖子好多直接放的ip+端口號,但是我本地會報錯,一定在加redis://192.168.2.128:6379這種格式的,可能是因為版本問題,也有可能就是誤導(dǎo)人的。
看到上面的報錯,感覺知道xml的錯誤了:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://redisson.org/schema/redisson
http://redisson.org/schema/redisson/redisson.xsd">
<beans profile="development">
<!--redisson -->
<!--<redisson:client id="redissonClient">
<redisson:single-server address="redis://182.92.97.141:5802"/>
</redisson:client>-->
</beans>
沒有設(shè)置密碼,一定不要把password屬性放上去,要不會報錯的~
spring整合redisson配置
配置方式
redis的部署方式有單節(jié)點部署、哨兵方式部署、集群方式部署3種方式
各種配置方式可以去看xsd文件:redisson-1.1.xsd
<xsd:element name="single-server"> // 單節(jié)點 <xsd:element name="sentinel-servers"> // 哨兵 <xsd:element name="cluster-servers"> // 集群 <xsd:element name="master-slave-servers"> // 主從
等其他方式
單節(jié)點配置standalone
單純的java代碼,基于單節(jié)點部署為了保證數(shù)據(jù)的備份,一般會添加一個節(jié)點作為slave來備份master節(jié)點上的數(shù)據(jù)
//創(chuàng)建配置
Config config = new Config();
//指定使用單節(jié)點部署方式
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
//創(chuàng)建客戶端(發(fā)現(xiàn)這一非常耗時,基本在2秒-4秒左右)
RedissonClient redisson = Redisson.create(config);
//首先獲取redis中的key-value對象,key不存在沒關(guān)系
RBucket<String> keyObject = redisson.getBucket("key");
//如果key存在,就設(shè)置key的值為新值value
//如果key不存在,就設(shè)置key的值為value
keyObject.set("value");
//最后關(guān)閉RedissonClient
redisson.shutdown();
spring整合pom
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.10.4</version>
</dependency>
<!--redis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
spring整合redisson.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://redisson.org/schema/redisson
http://redisson.org/schema/redisson/redisson.xsd">
<redisson:client id="standalone" name="aliasName1,aliasName2">
<redisson:single-server address="redis://127.0.0.1:6379" />
</redisson:client>
</beans>
哨兵配置sentinel
純java代碼
//創(chuàng)建配置
Config config = new Config();
//指定使用哨兵部署方式
config.useSentinelServers()
//設(shè)置sentinel.conf配置里的sentinel別名
//比如sentinel.conf里配置為sentinel monitor my-sentinel-name 127.0.0.1 6379 2,那么這里就配置my-sentinel-name
.setMasterName("my-sentinel-name")
//這里設(shè)置sentinel節(jié)點的服務(wù)IP和端口,sentinel是采用Paxos拜占庭協(xié)議,一般sentinel至少3個節(jié)點
//記住這里不是配置redis節(jié)點的服務(wù)端口和IP,sentinel會自己把請求轉(zhuǎn)發(fā)給后面monitor的redis節(jié)點
.addSentinelAddress("redis://127.0.0.1:26379")
.addSentinelAddress("redis://127.0.0.1:26389")
.addSentinelAddress("redis://127.0.0.1:26399");
//創(chuàng)建客戶端(發(fā)現(xiàn)這一非常耗時,基本在2秒-4秒左右)
RedissonClient redisson = Redisson.create(config);
//首先獲取redis中的key-value對象,key不存在沒關(guān)系
RBucket<String> keyObject = redisson.getBucket("key");
//如果key存在,就設(shè)置key的值為新值value
//如果key不存在,就設(shè)置key的值為value
keyObject.set("value");
//最后關(guān)閉RedissonClient
redisson.shutdown();
spring整合redis和redisson的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://redisson.org/schema/redisson http://redisson.org/schema/redisson/redisson.xsd">
<!-- 構(gòu)造JedisConnectionFactory實例,注入池配置poolConfig和哨兵配置sentinelConfig-->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!--<constructor-arg index="0" ref="redisSentinelConfiguration"/>-->
<!--<constructor-arg index="1" ref="jedisPoolConfig"/>-->
<constructor-arg ref="redisSentinelConfiguration"/>
<property name="poolConfig" ref="jedisPoolConfig"/>
<property name="database" value="${redis.database}"/>
</bean>
<!-- 配置JedisPoolConfig-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="minIdle" value="${redis.minIdle}"/>
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxTotal" value="${redis.maxTotal}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<property name="testWhileIdle" value="${redis.testWhileIdle}"/>
<property name="testOnReturn" value="${redis.testOnReturn}"/>
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
<property name="maxWaitMillis" value="${redis.maxWaitMillis}"/>
</bean>
<!-- 配置RedisSentinelConfiguration-->
<bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="${redis.masterName}"/>
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg index="0" value="${redis.host}"/>
<constructor-arg index="1" value="${redis.port}"/>
</bean>
</set>
</property>
</bean>
<!-- 用于緩存對象-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<!-- key -->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<!-- value -->
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
<!-- 用于緩存字符串-->
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
</bean>
<redisson:client id="redissonClient">
<!--master-name為redis的主節(jié)點名稱-->
<redisson:sentinel-servers master-name="mymaster">
<!-- 可以配置多個 -->
<redisson:sentinel-address value="redis://172.17.46.11:26379" />
</redisson:sentinel-servers>
</redisson:client>
</beans>
使用
@Autowired
@Lazy
private RedissonClient redissonClient;
/**
* @param key 具體鍵值
* @return 鎖對象
*/
public RReadWriteLock getLock(String key) {
return redissonClient.getReadWriteLock(key);
}
集群配置cluster
純java代碼
//創(chuàng)建配置
Config config = new Config();
//指定使用集群部署方式
config.useClusterServers()
// 集群狀態(tài)掃描間隔時間,單位是毫秒
.setScanInterval(2000)
//cluster方式至少6個節(jié)點(3主3從,3主做sharding,3從用來保證主宕機后可以高可用)
.addNodeAddress("redis://127.0.0.1:6379" )
.addNodeAddress("redis://127.0.0.1:6380")
.addNodeAddress("redis://127.0.0.1:6381")
.addNodeAddress("redis://127.0.0.1:6382")
.addNodeAddress("redis://127.0.0.1:6383")
.addNodeAddress("redis://127.0.0.1:6384");
//創(chuàng)建客戶端(發(fā)現(xiàn)這一非常耗時,基本在2秒-4秒左右)
RedissonClient redisson = Redisson.create(config);
//首先獲取redis中的key-value對象,key不存在沒關(guān)系
RBucket<String> keyObject = redisson.getBucket("key");
//如果key存在,就設(shè)置key的值為新值value
//如果key不存在,就設(shè)置key的值為value
keyObject.set("value");
//最后關(guān)閉RedissonClient
redisson.shutdown();
spring整合redisson配置方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://redisson.org/schema/redisson http://redisson.org/schema/redisson/redisson.xsd">
<!-- Redis 連接池配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="minIdle" value="${redis.minIdle}"/>
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxTotal" value="${redis.maxTotal}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<property name="testWhileIdle" value="${redis.testWhileIdle}"/>
<property name="testOnReturn" value="${redis.testOnReturn}"/>
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
<property name="maxWaitMillis" value="${redis.maxWaitMillis}"/>
<property name="timeBetweenEvictionRunsMillis" value="30000"/>
</bean>
<!-- jedisCluster 配置 -->
<!-- 自定義的工廠類,實現(xiàn)了FactoryBean<JedisCluster>接口 -->
<bean id="jedisCluster" class="com.xxxxx.JedisClusterFactory">
<!-- address: 集群配置 -->
<property name="address" value="${redisColony.host}"/>
<!-- timeout: 連接超時時間 -->
<property name="timeout" value="100000"/>
<!-- maxRedirections: 最大重定向 -->
<property name="maxRedirections" value="5"/>
<!-- 連接池 -->
<property name="genericObjectPoolConfig" ref="poolConfig"/>
</bean>
<!--redisson的實例 -->
<redisson:client id="redissonClient">
<redisson:cluster-servers>
<!-- 節(jié)點地址同redis集群的節(jié)點 -->
<redisson:node-address value="${redisColony.host1}"/>
<redisson:node-address value="${redisColony.host2}"/>
<redisson:node-address value="${redisColony.host3}"/>
<redisson:node-address value="${redisColony.host4}"/>
<redisson:node-address value="${redisColony.host5}"/>
<redisson:node-address value="${redisColony.host6}"/>
</redisson:cluster-servers>
</redisson:client>
</beans>
properties文件
redisColony.host = 172.17.46.11:36379,172.17.46.11:36381,172.17.45.12:36379,172.17.45.12:36381,172.17.45.13:36379,172.17.45.13:36381 redis.timeOut = 100000 redis.redirection = 5 redisColony.host1 = redis://172.17.46.11:36379 redisColony.host2 = redis://172.17.46.11:36381 redisColony.host3 = redis://172.17.45.12:36379 redisColony.host4 = redis://172.17.45.12:36381 redisColony.host5 = redis://172.17.45.13:36379 redisColony.host6 = redis://172.17.45.13:36381
使用方式與哨兵配置方式相同,@Autowired注入即可
主從部署方式(master/slave)
純java代碼
//創(chuàng)建配置
Config config = new Config();
//指定使用主從部署方式
config.useMasterSlaveServers()
//設(shè)置redis主節(jié)點
.setMasterAddress("redis://127.0.0.1:6379")
//設(shè)置redis從節(jié)點
.addSlaveAddress("redis://127.0.0.1:6380", "redis://127.0.0.1:6381");
//創(chuàng)建客戶端(發(fā)現(xiàn)這一非常耗時,基本在2秒-4秒左右)
RedissonClient redisson = Redisson.create(config);
//首先獲取redis中的key-value對象,key不存在沒關(guān)系
RBucket<String> keyObject = redisson.getBucket("key");
//如果key存在,就設(shè)置key的值為新值value
//如果key不存在,就設(shè)置key的值為value
keyObject.set("value");
//最后關(guān)閉RedissonClient
redisson.shutdown();
spring整合redisson.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:redisson="http://redisson.org/schema/redisson"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://redisson.org/schema/redisson
http://redisson.org/schema/redisson/redisson.xsd">
<redisson:client id="masterSlave">
<redisson:master-slave-servers master-address="redis://127.0.0.1:6379">
<redisson:slave-address value="redis://127.0.0.1:6380" />
<redisson:slave-address value="redis://127.0.0.1:6381" />
</redisson:master-slave-servers>
</redisson:client>
</beans>
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Security框架:如何使用CorsFilter解決前端跨域請求問題
這篇文章主要介紹了Security框架:如何使用CorsFilter解決前端跨域請求問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
談?wù)凧ava中Volatile關(guān)鍵字的理解
volatile這個關(guān)鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關(guān)鍵字,因為在程序中使用它往往會導(dǎo)致出人意料的結(jié)果,本文給大家介紹java中volatile關(guān)鍵字,需要的朋友參考下2016-03-03
Spring Cloud Hystrix線程池不足的解決方法
這篇文章主要介紹了Spring Cloud Hystrix線程池不足的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
Java如何使用遞歸查詢多級樹形結(jié)構(gòu)數(shù)據(jù)(多級菜單)
這篇文章主要介紹了Java如何使用遞歸查詢多級樹形結(jié)構(gòu)數(shù)據(jù)(多級菜單),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
關(guān)于SpringCloud的Bus消息總線圖文詳解
這篇文章主要介紹了關(guān)于SpringCloud的Bus消息總線圖文詳解,Spring Cloud Bus是用來將分布式系統(tǒng)的節(jié)點與輕量級消息系統(tǒng)鏈接起來的框架,它整合了Java的事件處理機制和消息中間件的功能,需要的朋友可以參考下2023-05-05

