springdata-redis的序列化规则

前置:本文基于springboot 2.1.6.RELEASE,redis版本为5.0.4

大家平时使用springdata-redis时,主要用到两个类:RedisTemplateStringRedisTemplate。使用这两个类来存储字符串或者对象时,大家有使用redis客户端来查看过存储的格式吗?

RedisTemplate

简单的示例

存入一个简单字符串。

redisTemplate.opsForValue().set("name","zs");

使用redis客户端查看
在这里插入图片描述
发现key已经不是一个简单的字符串了。可想,那么value肯定也不是一个简单的字符串了。

如果存入一个对象呀(此处的User类需要实现Serializable接口,后面会解释为什么)。

User user = new User();
user.setUsername("张三");
user.setPassword("123");
user.setAge(20);
redisTemplate.opsForValue().set("user",user);

在这里插入图片描述
可见key和value都被安装一定的格式处理过了,然后才存储到redis中。

查看原因

打开RedisAutoConfiguration查看

@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
		throws UnknownHostException {
	RedisTemplate<Object, Object> template = new RedisTemplate<>();
	template.setConnectionFactory(redisConnectionFactory);
	return template;
}

并没发现什么有用的信息。

那么继续查询RedisTemplate的源码

	@Override
	public void afterPropertiesSet() {

		super.afterPropertiesSet();

		boolean defaultUsed = false;
		// 发现这里redisTemplate设置了默认的序列化格式
		if (defaultSerializer == null) {
			// 默认使用的JdkSerializationRedisSerializer
			defaultSerializer = new JdkSerializationRedisSerializer(
					classLoader != null ? classLoader : this.getClass().getClassLoader());
		}
		// 默认为true
		if (enableDefaultSerializer) {

			if (keySerializer == null) {
				keySerializer = defaultSerializer;
				defaultUsed = true;
			}
			if (valueSerializer == null) {
				valueSerializer = defaultSerializer;
				defaultUsed = true;
			}
			if (hashKeySerializer == null) {
				hashKeySerializer = defaultSerializer;
				defaultUsed = true;
			}
			if (hashValueSerializer == null) {
				hashValueSerializer = defaultSerializer;
				defaultUsed = true;
			}
		}

		if (enableDefaultSerializer && defaultUsed) {
			Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
		}

		if (scriptExecutor == null) {
			this.scriptExecutor = new DefaultScriptExecutor<>(this);
		}

		initialized = true;
	}

在源码中发现使用了JdkSerializationRedisSerializer类来序列化。

RedisSerializer

通过查询继承关系,发现JdkSerializationRedisSerializer实现了RedisSerializer接口
在这里插入图片描述

结论:如果使用RedisTemplate,默认情况下 key、value、hashkey、hashvalue都是使用的jdk的Serializable方式序列化。所以我们如果要存对象,那么必须要实现Serializable接口。

那么我就想使用RedisTemplate,但是还想使用json方式存储,那么我们就要自己去定义RedisTemplate的bean,而不是用springboot自动配置的。

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 设置默认的序列化方式为json
        template.setDefaultSerializer(RedisSerializer.json());
        return template;
    }
}

那么再存对象

    @Test
    public void testRedisSet(){
        User user = new User();
        user.setUsername("张三");
        user.setPassword("123");
        user.setAge(20);
        redisTemplate.opsForValue().set("user",user);
    }

在这里插入图片描述
结果已经变为了json

注意:classpath中一定要有Jackson,如果使用springboot则不用担心,因为已经传递依赖了,并且springboot还自动配置了Jackson。

如果大家使用不是Jackson,而是fastjson,那么大家可以下去研究一下怎么配置哦。(提示:需要定义一个类,然后继承RedisSerializer,再然后在配置RedisTemplate时使用)

StringRedisTemplate

通过查询StringRedisTemplate的源码,可以发现

public StringRedisTemplate() {
	setKeySerializer(RedisSerializer.string());
	setValueSerializer(RedisSerializer.string());
	setHashKeySerializer(RedisSerializer.string());
	setHashValueSerializer(RedisSerializer.string());
}

StringRedisTemplate将序列化方式全部设置为RedisSerializer.string()了。
查看一下RedisSerializer.string()

static RedisSerializer<String> string() {
	return StringRedisSerializer.UTF_8;
}

可以发现使用的StringRedisSerializer来进行序列化的

请看实例代码

   @Test
   public void contextLoads() {
       stringRedisTemplate.opsForValue().set("name","张三");
   }

在这里插入图片描述
为什么中文变为2进制了呀,那是因为终端的问题。
大家使用redis-cli 连接时加一个 --raw参数就行了
在这里插入图片描述

总结

  1. redisTemplate
    可以存储任意类型,但是key、value、hashkey、hashvalue都会默认使用jdk的Serializable序列化存储,当然也可以自定义序列化方式
  2. stringRedisTemplate
    key、value、hashkey、hashvalue都只能存字符串。默认使用StringRedisSerializer来序列化
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值