使用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); } }