zoukankan      html  css  js  c++  java
  • Cacheable redis 宕机

    使用Cacheable注解Redis方法时,如果Redis服务器挂了,就直接抛出异常了,
    java.net.ConnectException: Connection refused: connect

    那么,有没有什么办法可以继续向下执行方法,从相关的数据库中查询数据,而不是直接抛出异常导致整个程序终止运行呢?

    经过反复翻看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);
        }
    
    
    }
    
    
  • 相关阅读:
    java自带线程池
    SQL 语句学习
    Eclipse 运行内存不足情况
    Eclipse的ant调用maven
    Elipse 无法启动问题(转)
    UI自动化测试实战之Select类实战(四)
    WebElement类方法实战(三)
    WebDriver浏览器属性详解(二)
    服务端测试之gRPC协议测试(一)
    服务端测试实战(一)
  • 原文地址:https://www.cnblogs.com/zhizhao/p/10151287.html
Copyright © 2011-2022 走看看