SpringBoot整合Redis要注意的那些

作者在重新学习Spring Boot整合Redis时,遇到java.lang.NoClassDefFoundError错误。原因是Spring Boot 2.0+默认redis client为lettuce,而程序未引入commons - pool2的jar包。解决方法一是增加pom依赖,二是yml配置不设lettuce.pool项,但后者不符合企业级要求。

前言

昨天自己在重新学习SpringBoot整合Redis时,遇到了一个问题java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig,错误很明显找不到需要的类。下面主要记录一下错误是怎么出线的,并且如何解决。

错误回顾

在SpringBoot 2.0+后,默认的redis client是lettuce而不是一直使用的jedis。此次出现的错误也是因为使用了lettuce出现的。
使用时的配置如下所示:

spring:
  redis:
    host: localhost
    port: 6379
    password:
    # 连接超时时间
    timeout: 10s
    # springboot默认使用lettuce
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms

pom使用最小的依赖进行测试验证。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

测试代码,期望结果是控制台显示 123456,表明redis可以正常使用。

@SpringBootTest
public class RedisServiceTest {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Test
    public void testRedis() {

        redisTemplate.opsForValue().set("test", "123456");

        String abec = (String) redisTemplate.opsForValue().get("test");
        System.out.println(abec);
    }
}

测试验证结果:
在这里插入图片描述

问题原因

跟踪一下源码发现就能轻松的发现问题:
既然使用的事lettuce client,程序中会通过yml配置匹配到LettuceConnectionConfiguration来创建连接池,所以看此类的源码就能得到答案。

/**
 * 创建lettuce工厂方法,该方法执行完我们会得到一个RedisConnectionFactory的实现类。 但是目前问题可以清楚的知道,该方法未执行完就出现了报错,所以我们看下面的代码。
 */
@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
LettuceConnectionFactory redisConnectionFactory(
		ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
		ClientResources clientResources) {
	LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(builderCustomizers, clientResources,
			getProperties().getLettuce().getPool());
	return createLettuceConnectionFactory(clientConfig);
}

/**
 * 生成lettuce客户端配置
 */
private LettuceClientConfiguration getLettuceClientConfiguration(
		ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
		ClientResources clientResources, Pool pool) {
	LettuceClientConfigurationBuilder builder = createBuilder(pool);
	applyProperties(builder);
	if (StringUtils.hasText(getProperties().getUrl())) {
		customizeConfigurationFromUrl(builder);
	}
	builder.clientOptions(createClientOptions());
	builder.clientResources(clientResources);
	builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
	return builder.build();
}

/**
 * lettuce客户端配置构造器
 */
private LettuceClientConfigurationBuilder createBuilder(Pool pool) {	
	// pool就是我们在yml配置文件中的lettuce.pool配置
	// 不为空执行的下面的方法
	if (pool == null) {
		return LettuceClientConfiguration.builder();
	}
	return new PoolBuilderFactory().createBuilder(pool);
}

最后执行的方法截图能明显发现错误
在这里插入图片描述

😂最后发现就是很简单的问题,很单纯的没有引入commons-pool2的jar包。问题原因就是自己不按照人要求做事,还逼逼赖赖~~ (无能的人儿啊)

解决方法

📢那就如她所愿,增加上新的pom依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

🤣宾狗-------验证通过
在这里插入图片描述

当然还有一种方法,就是yml配置文件中不要配置lettuce.pool配置项,这样初始化就执行默认的连接池了。🤔但是好像不配置的话又不符合企业级应用要求,所以还是当一个听话的好孩子吧,这样在之后出错的话就会有人站出来为你说一句: “他还是个孩子啊!!~”

🔚

这次记录就到这里啦~ 献给努力的我们。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶Yann

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值