功能一、实现发布订阅功能
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.2.4.RELEASE</version>
</dependency>
2、创建配置类LettuceConfig
package com.dunlingzi.lettuce.config;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Optional;
/**
* Lettuce配置
*
* @author dunlingiz
*/
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class LettuceConfig {
@Bean(destroyMethod = "shutdown")
public ClientResources clientResources() {
return DefaultClientResources.builder()
//I/O线程数
.ioThreadPoolSize(4)
//任务线程数
.computationThreadPoolSize(4)
.build();
}
@Bean
public ClientOptions clientOptions() {
return ClientOptions.builder()
//是否自动重连
.autoReconnect(false)
//连接激活之前是否执行PING命令
.pingBeforeActivateConnection(true)
.build();
}
@Bean
public RedisURI singleRedisUri(RedisProperties redisProperties) {
RedisURI.Builder builder = RedisURI.builder()
.withHost(redisProperties.getHost())
.withPort(redisProperties.getPort())
.withDatabase(redisProperties.getDatabase())
.withSsl(redisProperties.isSsl());
Optional.ofNullable(redisProperties.getClientName())
.ifPresent(builder::withClientName);
Optional.ofNullable(redisProperties.getTimeout())
.ifPresent(builder::withTimeout);
if (StringUtils.isNotBlank(redisProperties.getUsername())
&& StringUtils.isNotBlank(redisProperties.getPassword())) {
builder.withAuthentication(
redisProperties.getUsername()
, redisProperties.getPassword()
);
}
return builder.build();
}
@Bean
public RedisClient singleRedisClient(ClientResources clientResources, RedisURI singleRedisUri) {
RedisClient redisClient = RedisClient.create(clientResources, singleRedisUri);
redisClient.setOptions(clientOptions());
return redisClient;
}
@Bean
public StatefulRedisConnection<String, String> connection(RedisClient redisClient) {
return redisClient.connect();
}
}
3、封装Lettuce原生api
package com.dunlingzi.lettuce.utils;
import com.dunlingzi.common.utils.SpringUtils;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.pubsub.RedisPubSubAdapter;
import io.lettuce.core.pubsub.RedisPubSubListener;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
/**
* Lettuce客户端吧操作redis
*
* @author dunlingzi
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LettuceUtils {
private static final RedisClient CLIENT = SpringUtils.getBean(RedisClient.class);
/**
* 安全连接
*/
private static final StatefulRedisConnection<String, String> CONNECTION = CLIENT.connect();
/**
* 同步操作
*/
private static final RedisCommands<String, String> SYNC = CONNECTION.sync();
/**
* 发布消息
*
* @param message 消息内容
*/
public static void publish(String channel, String message) {
SYNC.publish(channel, message);
}
/**
* 发布通道消息
*
* @param channelKey 通道key
* @param msg 发送数据
* @param consumer 自定义处理
*/
public static void publish(String channelKey, String msg, Consumer<String> consumer) {
publish(channelKey, msg);
consumer.accept(msg);
}
/**
* 订阅通道接收消息
*
* @param channelKey 通道key
* @param consumer 自定义处理
*/
public static void subscribe(String channelKey, Consumer<String> consumer) {
//获取发布订阅操作命令工具
StatefulRedisPubSubConnection<String, String> pubsubConn = CLIENT.connectPubSub();
RedisPubSubAsyncCommands<String, String> pubsubCmd = pubsubConn.async();
pubsubCmd.subscribe(channelKey);
pubsubConn.addListener(new RedisPubSubAdapter<String, String>() {
/**
* 当订阅某个频道时,收到频道发布的消息时,调用此方法。
* @param channel Channel.
* @param message Message.
*/
@Override
public void message(String channel, String message) {
consumer.accept(message);
System.out.println("[message]" + channel + " -> " + message);
}
});
}
/**
* redis发布订阅监听器的接口描述
*
* @param <K>
* @param <V>
*/
@SuppressWarnings("unused")
static class RedisPubSubA<K, V> implements RedisPubSubListener<K, V> {
/**
* 当取消订阅某个频道时,调用此方法。count 参数表示当前订阅的客户端数。
*
* @param channel Channel
* @param count Subscription count.
*/
@Override
public void unsubscribed(K channel, long count) {
log.info("[unsubscribed]:{} --> count:{}", channel, count);
}
/**
* 当成功订阅某个频道时,调用此方法。count 参数表示当前订阅的客户端数。
*
* @param channel Channel
* @param count Subscription count.
*/
@Override
public void subscribed(K channel, long count) {
System.out.println("[subscribed]" + channel);
}
/**
* 当取消订阅某个模式时,调用此方法。count 参数表示当前订阅的客户端数。
*
* @param pattern Channel
* @param count Subscription count.
*/
@Override
public void punsubscribed(K pattern, long count) {
System.out.println("[punsubscribed]" + pattern);
}
/**
* 当成功订阅某个模式时,调用此方法。count 参数表示当前订阅的客户端数。
*
* @param pattern Pattern.
* @param count Subscription count.
*/
@Override
public void psubscribed(K pattern, long count) {
System.out.println("[psubscribed]" + pattern);
}
/**
* 当订阅某个模式时,收到符合模式的频道发布的消息时,调用此方法。
*
* @param pattern Pattern
* @param channel Channel
* @param message Message
*/
@Override
public void message(K pattern, K channel, V message) {
System.out.println("[message]" + pattern + " -> " + channel + " -> " + message);
}
/**
* 当订阅某个频道时,收到频道发布的消息时,调用此方法。
*
* @param channel Channel.
* @param message Message.
*/
@Override
public void message(K channel, V message) {
System.out.println("[message]" + channel + " -> " + message);
}
}
}
4、测试结果
订阅频道 channel=Lettuce
发布消息 channel=Lettuce message=hello world
监听器接收消息