使用Cacheable註解Redis方法時,若是Redis服務器掛了,就直接拋出異常了, java.net.ConnectException: Connection refused: connectjava
那麼,有沒有什麼辦法能夠繼續向下執行方法,從相關的數據庫中查詢數據,而不是直接拋出異常致使整個程序終止運行呢?redis
通過反覆翻看Spring的源碼和相關資料,並通過不斷驗證,得出了答案:有相關的方案!!!spring
原文:https://blog.csdn.net/l1028386804/article/details/82597154數據庫
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
# Redis服務器地址 spring.redis.host=192.168.2.2 # Redis服務器鏈接端口 spring.redis.port=6379 # 鏈接池中的最大空閒鏈接 spring.redis.jedis.pool.max-idle=8 # 鏈接池中的最小空閒鏈接 spring.redis.jedis.pool.min-idle=0 # 鏈接池最大鏈接數(使用負值表示沒有限制) spring.redis.jedis.pool.max-active=8 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) spring.redis.jedis.pool.max-wait=-1 # 鏈接超時時間(毫秒) spring.redis.timeout=1000
package org.springframework.cache.annotation; import org.springframework.cache.CacheManager; import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.interceptor.KeyGenerator; /** * An implementation of {@link CachingConfigurer} with empty methods allowing * sub-classes to override only the methods they're interested in. * * @author Stephane Nicoll * @since 4.1 * @see CachingConfigurer */ public class CachingConfigurerSupport implements CachingConfigurer { @Override public CacheManager cacheManager() { return null; } @Override public KeyGenerator keyGenerator() { return null; } @Override public CacheResolver cacheResolver() { return null; } @Override public CacheErrorHandler errorHandler() { return null; } }
package com.gxkj.config; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.Cache; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.lang.reflect.Method; /** * Created by yangqj on 2017/4/30. */ @Configuration @EnableCaching @EnableAspectJAutoProxy(exposeProxy = true) @Slf4j public class RedisConfig extends CachingConfigurerSupport { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.jedis.pool.max-idle}") private int maxIdle; @Value("${spring.redis.jedis.pool.max-wait}") private long maxWaitMillis; @Bean public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object o, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()); sb.append("-"); sb.append(method.getName()); sb.append("-"); for (Object param : params) { sb.append(param.toString()); } return sb.toString(); } }; } /** * 設置@cacheable 序列化方式 * * @return */ @Bean public RedisCacheConfiguration redisCacheConfiguration() { RedisSerializer serializer = new GenericJackson2JsonRedisSerializer(); RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)); return configuration; } @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(factory); // key序列化方式;(否則會出現亂碼;),可是若是方法上有Long等非String類型的話,會報類型轉換錯誤; // 因此在沒有本身定義key生成策略的時候,如下這個代碼建議不要這麼寫,能夠不配置或者本身實現ObjectRedisSerializer // 或者JdkSerializationRedisSerializer序列化方式; redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } /** * redis數據操做異常處理 這裏的處理:在日誌中打印出錯誤信息,可是放行 * 保證redis服務器出現鏈接等問題的時候不影響程序的正常運行,使得可以出問題時不用緩存 * * @return */ @Bean @Override public CacheErrorHandler errorHandler() { CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() { @Override public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) { RedisErrorException(exception, key); } @Override public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { RedisErrorException(exception, key); } @Override public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { RedisErrorException(exception, key); } @Override public void handleCacheClearError(RuntimeException exception, Cache cache) { RedisErrorException(exception, null); } }; return cacheErrorHandler; } protected void RedisErrorException(Exception exception,Object key){ log.error("redis異常:key=[{}]", key, exception); } }