当SpringBoot引用Redis依赖但没有配置Redis信息时
一、介绍
在SpringBoot
当中,我们往往使用多模块的方式对相对应的功能进行拆分。
当然Redis
也不例外,一般来说是在一个公共的模块中添加下面的依赖
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency >
那么只要是Jar
服务模块引用了这个公共模块,就自动引入了Redis
的相关依赖。
好,到了这边,就出现了一点小小的问题。
虽然引用了这个公共模块,但是没有配置相对应的Redis
信息,在项目启动后会出现异常报错
只需要一点小小的配置,就可以解决这个问题。
二、代码
大家都知道,SpringBoot
的stater
是如何配置运行的吧,问题出现的原因就出现在这里面
分别是RedisAutoConfiguration.java
和RedisReactiveAutoConfiguration.java
,平常的web
项目我们关注前者就好
里面代码并不复杂,看看源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package org.springframework.boot.autoconfigure.data.redis;import org.springframework.boot.autoconfigure.AutoConfiguration;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Import;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;@AutoConfiguration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { @Bean @ConditionalOnMissingBean(name = "redisTemplate") @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public RedisTemplate<Object, Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate <>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public StringRedisTemplate stringRedisTemplate (RedisConnectionFactory redisConnectionFactory) { return new StringRedisTemplate (redisConnectionFactory); } }
就是这里,如果我们没有redisTemplate
这个bean
的话,它就会自动生成了。
当然主要的redisConnectionFactory
的bean
生成,也可以仔细去看看,没有配置就默认给你一个localhost:6379
。
那么,我们应该如何避免他自动生成默认的redisTemplate
呢,我们又改动不了它的源代码。
如果没有头绪,那说明你还没有掌握@Condition
等相关的注解,可以看看我的这篇文章
SpringBoot中的@Conditional注解 | 半月无霜 (banmoon.top)
好的,那么可以这样解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package com.banmoon.business.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration @SuppressWarnings("all") @EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class}) public class RedisConfig { @Bean @ConditionalOnBean(RedisConnectionFactory.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public RedisTemplate<String, Object> redisTemplate (RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate <String, Object>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer (Object.class); ObjectMapper om = new ObjectMapper (); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer (); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
首先,排除掉两个Redis
自动配置类,我们自己来
其次,我们自己创建一个redisTemplate
的bean
,上面记得写上@ConditionalOnBean(RedisConnectionFactory.class)
,代表当存在RedisConnectionFactory
的bean
时,才生成redisTemplate
最后,其它模块引用,启动就不会再报错了
三、最后
你需要了解spring-boot-start
自动配置的机制。
如果写过,那么上面的将不再是问题。
我是半月,你我一同共勉!!!