扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
在Java中RedisTemplete提供了统一的API来操作Redis,比如插入一条String类型的数据,我可以用redisTemplate.opsForValue().set("name", "美羊羊");
SpringDataRedis可以接收任何类型的对象并将其转成Redis可以处理的字节,观察这段代码中set()方法的形参列表,发现传进去的key与value都被当作了Java对象Object来处理
将对象转成字节,这一操作好像和序列化非常相似,看一眼RedisTemplete实现过程,发现针对传入的不同key-value都会有相应的序列化器来操作:
进去可以看到,在头部定义的几个RedisSerializer类型变量都是null,均需要指定并初始化。
一般按照向set方法里传参的方式则会直接走默认的JDK序列化:
通过一次Debug来简单分析一下
首先,传入的value通过serialize()被转换成了字节数组
在serialize()方法的内部,则是将value值传入内部的convert()方法
而在convert()方法的内部则是调用了JDK内部的序列化工具,以流的形式将对象完成序列化
强制步入serialize()方法后,发现底层就是调用了ObjectoutputStream()来将对象转换成字节写入到Redis中!
但是去查看Redis却发现写入的数据不是以Java端写入的类型存入,而是以序列化的形式存入,并且key与value均被序列化。
如果这样的话:1.可读性很差2.内存占用大
上述的方式不推荐使用,我们可以人为改变一下RedisTemplete的序列化方式,即封装一个方法,指定key与value序列化的方式,不去使用默认的JDK内部序列化方式
就像这样:
@Configuration
public class ConfigRedis {@Bean
public RedisTemplateredisTemplate(RedisConnectionFactory connectionFactory) {// 创建RedisTemplate对象
RedisTemplatetemplate = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(connectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer =
new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
//静态方法 string()
template.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
其实就是创建一个RedisTemplete实例,并指定四个默认的序列化方式
主要就是将key序列化成String类型,将Object序列化成JSON类型数据而不是字节
并且可以在获取库中的数据时自动反序列化:User o = (User) redisTemplate.opsForValue().get("user:001");
按照这样的模式,以后根据需要想转换成什么样的序列化方式就可以转成什么样的方式了
最合理的字符串序列化方式对于我们这些初学者,自动化的方式确实很香(数据量少的情况下),由于实现反序列化时为了知道对象的类型而存在的那串数据:"@class": "com.yu7daily.Pojo.User"
,乍一看没什么,一旦数据量增多则会占用大量的内存,所以上述方式还是不建议使用
为了节省内存空间,实际开发中并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。SpringDataRedis提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式
由于继承了RedisTemplate就不需要再次去定义,直接使用该子类的实例化对象即可:
就像这样:
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final ObjectMapper mapper = new ObjectMapper(); //JSON工具
@Test
void testSaveUser() throws JsonProcessingException {// 创建对象
User user = new User("懒羊羊", 77);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入数据
stringRedisTemplate.opsForValue().set("user:002", json);
// 获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:002");
// 手动反序列化
User user2 = mapper.readValue(jsonUser, User.class);
System.out.println("user002 = " + user2);
}
运行测试类,存入对象数据后发现果然没有了“@class”数据
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流