redis集群,用注解@Cacheable见数据保存到缓存中,用template取出时出现了 java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.rampage.model.BankInfo错误。
通过网上查找,找到以下解决方法,重写ObjectMapper,并替换template和cachemanager中的ObjectMapper,两个地方,不要漏了,然后看代码吧。
网上还有中解决方法是注掉devtools的jar包,当时我没有引用该包,所以不是该包引起的问题。
@Configuration
@PropertySource("classpath:application.yml")
public class RedisConfig {
// @Value("${redis.timeout}")
@Value("${spring.redis.timeout}")
private Integer timeout;
// @Value("${redis.maxIdle}")
@Value("${spring.redis.jedis.pool.max-idle}")
private Integer maxIdle;
// @Value("${redis.maxTotal}")
@Value("${spring.redis.jedis.pool.max-active}")
private Integer maxTotal;
// @Value("${redis.maxWaitMillis}")
@Value("${spring.redis.jedis.pool.max-wait}")
private Integer maxWaitMillis;
// @Value("${redis.minEvictableIdleTimeMillis}")
// private Integer minEvictableIdleTimeMillis;
//
// @Value("${redis.numTestsPerEvictionRun}")
// private Integer numTestsPerEvictionRun;
//
// @Value("${redis.timeBetweenEvictionRunsMillis}")
// private long timeBetweenEvictionRunsMillis;
//
// @Value("${redis.testOnBorrow}")
// private boolean testOnBorrow;
//
// @Value("${redis.testWhileIdle}")
// private boolean testWhileIdle;
@Value("${spring.redis.cluster.nodes}")
private String clusterNodes;
@Value("${spring.redis.cluster.max-redirects}")
private Integer mmaxRedirectsac;
/**
* JedisPoolConfig 连接池
*
* @return
*/
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大空闲数连接数,默认8个
jedisPoolConfig.setMaxIdle(maxIdle);
// 最大连接数,默认8个
jedisPoolConfig.setMaxTotal(maxTotal);
// 最大建立连接等待时间
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
// // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
// jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// // 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
// jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
// // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
// jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// // 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
// jedisPoolConfig.setTestOnBorrow(testOnBorrow);
// // 在空闲时检查有效性, 默认false
// jedisPoolConfig.setTestWhileIdle(testWhileIdle);
return jedisPoolConfig;
}
/**
* 注意:
* 这里返回的JedisCluster是单例的,并且可以直接注入到其他类中去使用
*
* @return
*/
@Bean
public JedisCluster getJedisCluster(JedisPoolConfig jedisPoolConfig) {
String[] serverArray = clusterNodes.split(",");//获取服务器数组(这里要相信自己的输入,所以没有考虑空指针问题)
Set<HostAndPort> nodes = new HashSet<>();
for (String ipPort : serverArray) {
String[] ipPortPair = ipPort.split(":");
nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
}
return new JedisCluster(nodes, timeout, mmaxRedirectsac, jedisPoolConfig);//需要密码连接的创建对象方式
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
MyObjectMapper objectMapper = new MyObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
MyObjectMapper objectMapper = new MyObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();
return cacheManager;
}
public class MyObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
public MyObjectMapper() {
super();
// 去掉各种@JsonSerialize注解的解析
this.configure(MapperFeature.USE_ANNOTATIONS, false);
// 只针对非空的值进行序列化
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 将类型序列化到属性json字符串中
this.enableDefaultTyping(DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// 对于找不到匹配属性的时候忽略报错
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 不包含任何属性的bean也不报错
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
}