SpringBoot中RedisTemplate序列化的几种方式
SpringBoot2.1.5
Redis5.0.3
问题
当调用opsForValue方法时会传入当前redistemplate对象,以keySerializer为例,它默认为null,如果等于null就被赋值dafaultSerializer,默认dafaultSerializer也为空,最终keySerializer就被赋值为JdkSerializationRedisSerializer,所以没有设置序列化方式的时候redistemplate使用的序列化方式为JdkSerializationRedisSerializer,所以我们存入key前面会带上一串东西,而StringRedisTemplate使用的是 StringRedisSerializer,序列化的方式不一样,所以使用的时候key就不会出现一串字符串。
RedisTemplate的序列化类型
SpringBoot提供的Redis存储序列化方式,常用的有以下几种:
JdkSerializationRedisSerializer:将数据序列化为对象
StringRedisSerializer:将数据序列化为字符串
Jackson2JsonRedisSerializer:将数据序列化为json
GenericJackson2JsonRedisSerializer
三、Jackson2JsonRedisSerializer
就序列化和反序列化性能来说,Jackson2JsonRedisSerializer方式效率是最高的,同时在redis中也有很好的可读性。
序列化处理类
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Redis对json序列化处理
*/
@Configuration
public class RedisConfig_JacksonSerializer
{
@Bean
public RedisTemplate <String, Object> getRedisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
// 使用Jackson2JsonRedisSerialize替换默认序列化方式
Jackson2JsonRedisSerializer<?> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//启用默认的类型
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//序列化类,对象映射设置
jackson2JsonRedisSerializer.setObjectMapper(om);
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
Redis查询结果
[root@localhost ~]# redis-cli -c -h 192.168.236.128 -p 6379 -a 123456
192.168.236.128:6380> keys *
1) "dept"
192.168.236.128:6380> hget dept id
"\"1006\""
192.168.236.128:6380> hget dept name
"\"zhangsan6\""
192.168.236.128:6380> hget dept level
"6"
二、StringRedisSerializer
Springboot提供的StringRedisTemplate模板操作是用StringRedisSerializer来进行序列化。该序列化方式只能保存字符串,不能保存对象。
序列化处理类
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.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig_StringSerializer {
@Bean
public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
return redisTemplate;
}
}
Redis查询结果
[root@localhost conf]# redis-cli -c -h 192.168.236.128 -p 6380 -a 123456
192.168.236.128:6380> keys *
1) "dept"
192.168.236.128:6380> hget dept id
"1006"
192.168.236.128:6380> hget dept name
"zhangsan6"
192.168.236.128:6380> hget dept level
"6"
一、JdkSerializationRedisSerializer
spring-data-redis的RedisTemplate模板类在操作redis时默认使用JdkSerializationRedisSerializer进行序列化,并在Redis中存储序列化后的二进制字节。所以就占用存储空间来说,JdkSerializationRedisSerializer方式序列化之后长度是最小的。
序列化处理类
SpringData提供的RedisTemplate只支持基本类型的操作,不能处理对象的存储。为了方便对象的操作,我们需要自定义一个RedisTemplate来操作对象。
自定义处理对象的存储,使用RedisTemplate模板加载序列化工具类RedisObjectSerializer。
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.StringRedisSerializer;
/**
* JDK序列化处理—自定义处理对象的存储
* 使用RedisTemplate模板加载序列化工具类RedisObjectSerializer
*/
@Configuration
public class RedisConfig_JDKSerializer
{
@Bean
public RedisTemplate<Object, Object> getRedisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> rt = new RedisTemplate<>();
rt.setConnectionFactory(connectionFactory);
rt.setKeySerializer(new StringRedisSerializer());
rt.setValueSerializer(new RedisObjectSerializer());
return rt;
}
}
/**
* 自定义 RedisObjectSerializer.java
*/
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class RedisObjectSerializer implements RedisSerializer<Object>
{
private Converter<Object, byte[]> serializingConverter = new SerializingConverter();
private Converter<byte[], Object> deserializingConverter = new DeserializingConverter();
@Override
public byte[] serialize(Object obj) throws SerializationException
{
if(obj == null) {
return new byte[0];
}
//将对象转换为字节数组
return this.serializingConverter.convert(obj);
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length == 0)
return null;
return this.deserializingConverter.convert(bytes);
}
}
Redis查询结果(旧的)
[root@localhost ~]# redis-cli -c -h 192.168.236.128 -p 6380 -a 123456
192.168.236.128:6380> keys *
1) "\xac\xed\x00\x05t\x00\x04dept"
192.168.236.128:6380> hget dept id
"\xac\xed\x00\x05t\x00\x041002"
192.168.236.128:6380> hget dept name
"\xac\xed\x00\x05t\x00\tzhangsan2"
192.168.236.128:6380> hget dept level
"\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x02"
Junit测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { App.class })
public class AppTest
{
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void test() throws Exception
{
this.redisTemplate.opsForHash().put("dept", "id", "1006");
this.redisTemplate.opsForHash().put("dept", "name", "zhangsan6");
this.redisTemplate.opsForHash().put("dept", "level", 6);
System.out.println(this.redisTemplate.opsForHash().keys("dept"));
System.out.println(this.redisTemplate.opsForHash().size("dept"));
System.out.println(this.redisTemplate.opsForHash().values("dept"));
}
}
完
参考 资料
Springboot2整合Redis以及jackson序列化
https://blog.youkuaiyun.com/zaincs/article/details/84399584
基于Spring的项目中Redis存储对象使用Jackson序列化方式
https://www.zifangsky.cn/1366.html
SpringBoot整合Redis序列化配置
https://blog.youkuaiyun.com/fx9590/article/details/99424568
在Service的实现类中单独指定Serializer
https://www.cnblogs.com/EasonJim/p/7805665.html
Springboot中redis序列化问题分析
https://blog.youkuaiyun.com/u012031408/article/details/89478241