最近在项目中集成springCache,在对Map类型的返回值进行反序列化出现key类型不匹配,Map<Integer,AcademicQualificationsEntity>
, 类型被反序列化为Map<String,AcademicQualificationsEntity>
springCache配置
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.*;
@EnableConfigurationProperties(CacheProperties.class)
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// key 指定序列化 -string
config= config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
// value 指定序列化-Jackson
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
缓存方法
@Cacheable(key = "#root.caches[0].name", value = "ACADEMIC")
@Override
public Map<Integer, AcademicQualificationsEntity> cacheAcademicInfo() {
return this.baseMapper.selectAllInfoEncapsulatedMap();
}
测试方法
@Test
public void academicTest() {
Map<Integer, AcademicQualificationsEntity> map = academicQualificationsService.cacheAcademicInfo();
System.out.println(map);
for (Integer key : map.keySet()) {
System.out.println(map.get(key));
}
}
测试结果
// for (Integer key:map.keySet()) 此处出现类型转换异常
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
redis 客户端中的json串
{
"1": {
"@class": "com.community.healthy.entity.AcademicQualificationsEntity",
"id": 1,
"degree": "初等教育",
"parentId": 0,
"isActive": 0,
"version": 0
},
"2": {
"@class": "com.community.healthy.entity.AcademicQualificationsEntity",
"id": 2,
"degree": "中等教育",
"parentId": 0,
"isActive": 0,
"version": 0
},
"3": {
"@class": "com.community.healthy.entity.AcademicQualificationsEntity",
"id": 3,
"degree": "高等教育",
"parentId": 0,
"isActive": 0,
"version": 0
},
"@class": "java.util.HashMap"
}
Map<Integer, AcademicQualificationsEntity> map = academicQualificationsService.cacheAcademicInfo();
调用返回的实际类型为Map<String,AcademicQualificationEntity>
但是编译器应该提供类型检查<Integer,AcademicQualificationEntity>
Spring Cache 为什么出现了Map<>
转换异常并且欺骗了编译器呢?
请问这个问题该如何解决呢?
当使用 Jackson 反序列化 Map 时,默认情况下,所有的键都会被当作字符串处理。这就是为什么您遇到了这个问题。要解决这个问题,您需要自定义一个 Redis 序列化器,以便在反序列化时可以将键转换回 Integer 类型。
以下是一个自定义的 Redis 序列化器示例,可以解决这个问题:
然后,在您的 RedisCacheConfig 类中使用这个自定义序列化器替换 GenericJackson2JsonRedisSerializer:
这将确保在反序列化 Map 时将键正确地转换回 Integer 类型。