Jedis SpringBoot无法序列化和反序列化Map<String, Object>
Jedis SpringBoot cannot serialize and deserialize Map<String, Object>
将@Cacheable 注释添加到我的休息方法之一后出现以下错误:
"status": 500,
"error": "Internal Server Error",
"message": "class java.util.ArrayList cannot be cast to class java.util.Map (java.util.ArrayList and java.util.Map are in module java.base of loader 'bootstrap')",
方法声明为:
@Cacheable("loadDevicesFloors")
@GetMapping("/floors/all-devices")
public Map<String, DevicesFloorDTO> loadDevicesFloors() {...
DevicesFloorDTO 如下所示:
public class DevicesFloorDTO implements Serializable {
private final List<DeviceDTO> deviceDTOs;
private final String floorName;
private final Integer floorIndex;
public DevicesFloorDTO(List<DeviceDTO> devicesDtos, String floorName, Integer floorIndex) {
this.deviceDTOs = devicesDtos;
this.floorName = floorName;
this.floorIndex = floorIndex;
}...
另外我的@Bean redisTemplate 方法实现:
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConFactory
= new JedisConnectionFactory();
jedisConFactory.setHostName(redisHost);
jedisConFactory.setPort(redisPort);
jedisConFactory.setPassword(redisPassword);
return jedisConFactory;
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
有人知道这个实现有什么问题吗?没有 @Cacheable 它按预期工作,但在添加 @Cacheable 后发生错误。我进行了很多搜索,但仍然不知道导致此错误的原因以及如何解决此问题。任何评论都可能有帮助。太感谢了!
您为映射 Map<String, DevicesFloorDTO>
指定的泛型将在 serialization/deserialization 期间在运行时不可用。在 Reids 中,您尝试将对象保存为哪种格式?它们是保存为 JSON(字符串)还是二进制文件?
我们在 GenericJackson2JsonRedisSerializer
上取得了成功,因为它将 class 信息保存在 JSON 字符串中,因此 Redis 确切地知道如何重新创建对象。
还有一些情况需要包装器对象才能正确 serialize/deserialize 个对象。
@Bean
public RedisCacheManager cacheManager( RedisConnectionFactory redisConnectionFactory,
ResourceLoader resourceLoader ) {
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
.builder( redisConnectionFactory )
.cacheDefaults( determineConfiguration() );
List<String> cacheNames = this.cacheProperties.getCacheNames();
if ( !cacheNames.isEmpty() ) {
builder.initialCacheNames( new LinkedHashSet<>( cacheNames ) );
}
return builder.build();
}
private RedisCacheConfiguration determineConfiguration() {
if ( this.redisCacheConfiguration != null ) {
return this.redisCacheConfiguration;
}
CacheProperties.Redis redisProperties = this.cacheProperties.getRedis();
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
ObjectMapper mapper = new Jackson2ObjectMapperBuilder()
.modulesToInstall( new SimpleModule().addSerializer( new NullValueSerializer( null ) ) )
.failOnEmptyBeans( false )
.build();
mapper.enableDefaultTyping( ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY );
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer( mapper );
//get the mapper b/c they registered some internal modules
config = config.serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( serializer ) );
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();
config = config.computePrefixWith( cacheName -> cacheName + "::" );
}
return config;
}
将@Cacheable 注释添加到我的休息方法之一后出现以下错误:
"status": 500,
"error": "Internal Server Error",
"message": "class java.util.ArrayList cannot be cast to class java.util.Map (java.util.ArrayList and java.util.Map are in module java.base of loader 'bootstrap')",
方法声明为:
@Cacheable("loadDevicesFloors")
@GetMapping("/floors/all-devices")
public Map<String, DevicesFloorDTO> loadDevicesFloors() {...
DevicesFloorDTO 如下所示:
public class DevicesFloorDTO implements Serializable {
private final List<DeviceDTO> deviceDTOs;
private final String floorName;
private final Integer floorIndex;
public DevicesFloorDTO(List<DeviceDTO> devicesDtos, String floorName, Integer floorIndex) {
this.deviceDTOs = devicesDtos;
this.floorName = floorName;
this.floorIndex = floorIndex;
}...
另外我的@Bean redisTemplate 方法实现:
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConFactory
= new JedisConnectionFactory();
jedisConFactory.setHostName(redisHost);
jedisConFactory.setPort(redisPort);
jedisConFactory.setPassword(redisPassword);
return jedisConFactory;
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
有人知道这个实现有什么问题吗?没有 @Cacheable 它按预期工作,但在添加 @Cacheable 后发生错误。我进行了很多搜索,但仍然不知道导致此错误的原因以及如何解决此问题。任何评论都可能有帮助。太感谢了!
您为映射 Map<String, DevicesFloorDTO>
指定的泛型将在 serialization/deserialization 期间在运行时不可用。在 Reids 中,您尝试将对象保存为哪种格式?它们是保存为 JSON(字符串)还是二进制文件?
我们在 GenericJackson2JsonRedisSerializer
上取得了成功,因为它将 class 信息保存在 JSON 字符串中,因此 Redis 确切地知道如何重新创建对象。
还有一些情况需要包装器对象才能正确 serialize/deserialize 个对象。
@Bean
public RedisCacheManager cacheManager( RedisConnectionFactory redisConnectionFactory,
ResourceLoader resourceLoader ) {
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
.builder( redisConnectionFactory )
.cacheDefaults( determineConfiguration() );
List<String> cacheNames = this.cacheProperties.getCacheNames();
if ( !cacheNames.isEmpty() ) {
builder.initialCacheNames( new LinkedHashSet<>( cacheNames ) );
}
return builder.build();
}
private RedisCacheConfiguration determineConfiguration() {
if ( this.redisCacheConfiguration != null ) {
return this.redisCacheConfiguration;
}
CacheProperties.Redis redisProperties = this.cacheProperties.getRedis();
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
ObjectMapper mapper = new Jackson2ObjectMapperBuilder()
.modulesToInstall( new SimpleModule().addSerializer( new NullValueSerializer( null ) ) )
.failOnEmptyBeans( false )
.build();
mapper.enableDefaultTyping( ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY );
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer( mapper );
//get the mapper b/c they registered some internal modules
config = config.serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( serializer ) );
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();
config = config.computePrefixWith( cacheName -> cacheName + "::" );
}
return config;
}