Spring Boot 使用Redis拒絕連線以及獲取不到連線池
使用環境
- 使用spring boot構建上層服務專案
- redis快取相關方法寫到公共工具類,被上層服務依賴
common-utils
- redis是安裝在本地虛擬機器中
啟動服務,首先程式報錯為拒絕連線:
然後使用本地視覺化工具進行測試連線,顯示同樣的錯誤connection refused
解決方法:
- 首先在
redis.conf
中註釋掉bind 127.0.0.1
這一行,其意思是隻允許本地訪問連線,其他Ip都將被拒絕. - 如果第一步操作過後,依然拒絕連線,可能為redis部署機器的防火牆沒有關閉或者網路不通,進行如下操作:
2.1. 首先檢查自己的網路,是否可以ping通
2.2. 檢查埠netstat -tunlp |grep 6379
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 3227/redis-server *
,檢視結果也是ok的.
2.3 伺服器防火牆的問題,關了防火牆試下:systemctl stop firewalld.service
(我的遠端機器是centos7)
補充:systemctl stop firewalld.service
#停止firewallsystemctl disable firewalld.service
#禁止firewall開機啟動
執行下面這段命令就可以開放6379埠了firewall-cmd --zone=public --add-port=6379/tcp --permanent
至此本地視覺化工具已經連線可用;
啟動spring boot
程式,無法獲取到RedisTemplate
jar
包使用@Configuration
配置redis快取
程式碼如下:
@Configuration @EnableCaching @PropertySource("classpath:RedisConfig.properties") public class RedisConfig extends CachingConfigurerSupport{ @Bean public KeyGenerator wiselyKeyGenerator(){ return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } @Bean public CacheManager cacheManager( @SuppressWarnings("rawtypes") RedisTemplate redisTemplate) { return new RedisCacheManager(redisTemplate); } @Bean public RedisTemplate<String, String> redisTemplate( RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(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); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
屬性檔案在common-util
包中,RedisConfig.properties
內容如下:
# REDIS (RedisProperties)
# Redis資料庫索引(預設為0)
spring.redis.database=0
# Redis伺服器地址
spring.redis.host=192.168.22.111
# Redis伺服器連線埠
spring.redis.port=6379
# Redis伺服器連線密碼(預設為空)
spring.redis.password=
# 連線池最大連線數(使用負值表示沒有限制)
spring.redis.pool.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連線池中的最大空閒連線
spring.redis.pool.max-idle=8
# 連線池中的最小空閒連線
spring.redis.pool.min-idle=0
# 連線超時時間(毫秒)
開始懷疑spring boot不會自動掃描jar包中的@Configuration
註解,測試過後,這個是完全可以的;
接下來開始除錯,發現redis使用的是預設連線(127.0.0.1:6379)並沒有讀取到我的屬性檔案,原來spring boot不能預設讀取jar包中的屬性檔案,需要我們手工指定裝載進來:
在@Configuration
註解那裡加上@PropertySource("classpath:RedisConfig.properties")
接下來問題又出現了:
Description:
Field template in org.pekxxoo.redis.RedisUtil required a single bean, but 2 were found:
- redisTemplate: defined by method 'redisTemplate' in class path resource [org/pekxxoo/redis/RedisConfig.class]
- stringRedisTemplate: defined by method 'stringRedisTemplate' in class path resource [org/springframework/boot/autoconfigure/data/redis/RedisAutoConfiguration$RedisConfiguration.class]
看說明,可以知道,是因為@Autowired
在注入時,是匹配型別的,如果存在兩個一個型別的例項時就會報錯,報錯資訊指出,一個redisTemplate
是在我的RedisConfig.class
中配置的,另一個是RedisAutoConfiguration
中進行宣告的,因此兩種解決方案:
- 在啟動類處加上註解:
@EnableAutoConfiguration(exclude = RedisAutoConfiguration.class)
關閉自動注入配置; - 在RedisUtil.class注入時結合
@Qualifier("")
註解:
@Qualifier("redisTemplate")
@Autowired
private RedisTemplate<String,String> template;
至此spring boot
結合redis
快取終於啟動成功;