springboot2集成redis客户端Lettuce

281 阅读2分钟

功能一、实现发布订阅功能

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 订阅1.png 发布消息 channel=Lettuce message=hello world 发布1.png 监听器接收消息 监听器监听到消息.png

5、参考

Lettuce官网

博客园 - throwable - Redis高级客户端Lettuce详解