问题背景:
有同事反应,她修改了架构的名称做项目,本地没有问题,丢到服务器上出现反序列失败的问题。
报错显示该不存在的类是该服务器上另一个项目的。
问题根源:
多项目共用一个redis,若存在相同的key时,会被覆盖,导致反序列化获取该key时,存在找不到该类的情况。
解决方案:
1. 每个项目给key值增加前缀,这样在共用redis时,不存在key值冲突。
1)重写key值处理的类
import org.springframework.data.redis.serializer.RedisSerializer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 为redis key 统一加上前缀
*/
public class RedisKeySerializer implements RedisSerializer<String> {
/**
* 编码格式
*/
private final Charset charset;
/**
* 前缀
*/
private final String PREFIX_KEY = "gsi:";
public RedisKeySerializer() {
this(StandardCharsets.UTF_8);
}
public RedisKeySerializer(Charset charset) {
this.charset = charset;
}
/**
* 反序列化
*/
@Override
public String deserialize(byte[] bytes) {
String key = new String(bytes, charset);
return key.replace(PREFIX_KEY, "");
}
/**
* 序列化
*/
@Override
public byte[] serialize(String key) {
key = PREFIX_KEY + key;
return key.getBytes(charset);
}
}
2) 调整RedisConfig类
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置类
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
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);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
2. 在Redis中默认有16个库,利用redis可以分库的特性,各个项目使用不同的redis库database,这样也可以避免key值冲突的问题。
#redis配置 redis: database: 1 host: 127.0.0.1 port: 6379 password: jedis: pool: max-active: 8 max-wait: -1 max-idle: 8 min-idle: 0 timeout: 5000
结束!
版权声明:本文为xhuiting原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。