在上一篇中,提到了使用配置文件来定义连接信息,由于前面讲的都是框架自动使用redis缓存数据,那么如果出现了异常又该怎么处理?
这里我们修改一下配置信息,让redis故意连接不上,看看异常信息。
修改一下yml里port端口,然后再执行一下add或者query操作,看控制台报错信息。
打开AbstractCacheInvoker类,看到里面有put,get,evict等方法,就是对应在repository的注解,还有个无参的构造方法里初始化了一个SimpleCacheErrorHandler。
打开SimpleCacheErrorHandler类
这个类就是处理redis缓存异常的类,发现里面只是简单的在异常时throw Exception,这也导致了如果redis异常,那么程序就会抛出异常,像query时,如果redis异常,那程序就不再往下进行,也不再进行查数据库操作,其实这样是有风险的,我们希望redis异常后,db能继续响应客户端请求,然后记录这次异常,回头再处理。
处理redis异常,我们需要自定义CacheErrorHandler来替代默认的SimpleCacheErrorHandler。
打开之前的Redis配置类RedisCacheConfig,继承CachingConfigurerSupport,这个CachingConfigurerSupport就是供我们来自定义一些Cache相关配置的。
重写Override errorHandler方法:
package com.tianyalei.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
/**
* Created by wuwf on 17/4/24.
*/
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.pool.max-active}")
private int maxActive;
@Value("${spring.redis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.pool.max-wait}")
private int maxWait;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setPassword(password);
factory.setHostName(host);
factory.setPort(port);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxActive);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxWaitMillis(maxWait);
factory.setPoolConfig(jedisPoolConfig);
return factory;
}
@Bean
public RedisTemplate<String, String> getRedisTemplate() {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
//key序列化方式,但是如果方法上有Long等非String类型的话,会报类型转换错误
RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
redisTemplate.setKeySerializer(redisSerializer);
// redisTemplate.setHashKeySerializer(redisSerializer);
// redisTemplate.setValueSerializer(redisSerializer);
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);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
System.out.println(key);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
System.out.println(value);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
}
};
return cacheErrorHandler;
}
}
然后就可以在对应的方法上加自己的处理。
再试一下save或者get操作,发现系统已经不报错了,进入了我们自定义的errorHandler方法中。
下一篇继续探讨redis的其他使用方法。