当前位置:网站首页>Redis 序列化 GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializer的区别
Redis 序列化 GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializer的区别
2022-07-02 06:33:00 【保护我方胖虎】
文章目录
/** * 实例化 RedisTemplate 对象 * @return */
@Bean
public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key 都使用String 序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
GenericJackson2JsonRedisSerializer
GenericJackson2JsonRedisSerializer序列化时,会保存序列化的对象的完全限定名,从redis获取数据时即可直接反序列化成指定的对象
通用参数如下:
List<Student> students = new ArrayList<>();
Student xm = new Student("小明", 12);
Student ph = new Student("胖虎", 12);
students.add(xm);
students.add(ph);
(1)VALUE 存普通对象
存:
Student xm = new Student("小明", 12);
redisTemplate.opsForValue().set(xm.getName(), xm);

值中附带了实体信息
取:
Student xmCache = (Student)redisTemplate.opsForValue().get(xm.getName());
// Student(name=小明, age=12)
System.out.println(xmCache);
结论:GenericJackson2JsonRedisSerializer 序列化方式 可直接存储VALUE为对象,且从Redis获取可进行强转
(2)VALUE 存对象集合
存:
redisTemplate.opsForSet().add("students-genericJackson2JsonRedisSerializer", students);
redisTemplate.opsForValue().set("students-str", students);

值中既有实体类完全限定名又有集合类型
–

具体值中携带了实体类完全限定名
取:
List<Student> studentCache = (List<Student>) redisTemplate.opsForValue().get("students-str");
Set<Object> members = redisTemplate.opsForSet().members("students-genericJackson2JsonRedisSerializer");
// [Student(name=小明, age=12), Student(name=胖虎, age=12)]
System.out.println(studentCache);
// [Student(name=胖虎, age=12), Student(name=小明, age=12)]
System.out.println(members);
结论:GenericJackson2JsonRedisSerializer 序列化方式 可直接存储VALUE为对象集合,且从Redis获取可进行强转
(3)VALUE 存JSON字符串
redisTemplate.opsForValue().set(ph.getName(), JSON.toJSONString(ph));
存:

无@class字段,且jSON字符串中含有转义符
取:
Object o = redisTemplate.opsForValue().get(ph.getName());
System.out.println(o);

注意点:因为这里存是JSON字符串,所以取数据时候,也无法直接强制转为Student对象,我们需要手动调用方法,将JSON字符串转换为JAVA对象
redisTemplate.opsForValue().set(ph.getName(), JSON.toJSONString(ph));
Object o = redisTemplate.opsForValue().get(ph.getName());
// Student(name=胖虎, age=12)
System.out.println(o == null ? null : JSON.parseObject(o.toString(), Student.class));
结论:GenericJackson2JsonRedisSerializer 序列化方式 可直接存储VALUE为JSON字符串形式,且从Redis获取后不可进行强转,需要将结果转为字符串,再将JSON字符串转为自己需要的对象或对象集合
(4)管道Pipelined存数据
存:
List<Student> students = new ArrayList<>();
Student xm = new Student("小明", 12); Student ph = new Student("胖虎", 12);
students.add(xm); students.add(ph);
redisTemplate.executePipelined((RedisCallback) conn -> {
students.forEach(s -> conn.set(s.getName().getBytes(), JSON.toJSONString(s).getBytes()));
return null;
});


管道操作的数据并没有@class 实体类属性,实体类完全限定名丢失,那么这个时候还能否获取数据呢?
答案是不能
取:
取完直接强转:
Student xmCache = (Student)redisTemplate.opsForValue().get(xm.getName());
System.out.println(xmCache);

GET取完不强转
Object xmCache = redisTemplate.opsForValue().get(xm.getName());
System.out.println(xmCache);

MGET 批量获取
List<Object> objectList = redisTemplate.opsForValue().multiGet(students.stream().map(Student::getName).collect(Collectors.toList()));
System.out.println(objectList);
return objectList;

ERROR 16400 — [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property ‘@class’
at [Source: (byte[])"{“age”:12,“name”:“小明”}"; line: 1, column: 26]; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property ‘@class’
at [Source: (byte[])"{“age”:12,“name”:“小明”}"; line: 1, column: 26]] with root cause
翻译过来的意思是:无法读取 JSON:尝试解析 [简单类型,类 java.lang.Object] 的子类型时缺少类型 ID:缺少类型 id 属性“@class”
结论: 使用GenericJackson2JsonRedisSerializer 序列化进行管道操作后,实体类@class属性会丢失,再次从redis获取数据将无法成功反序列化
Jackson2JsonRedisSerializer
通用参数如下:
List<Student> students = new ArrayList<>();
Student ys = new Student("亚索", 12);
Student mw = new Student("蛮王", 12);
students.add(ys);
students.add(mw);
(1)VALUE 存普通对象
存:
redisTemplate.opsForValue().set(ys.getName(), ys);
redisTemplate.opsForValue().set(mw.getName(), mw);

取:
Student ysCache = (Student)redisTemplate.opsForValue().get(ys.getName());
System.out.println(ysCache);
发现报错:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.leilei.entity.Student

断点调试:获取的ysCache 实际是一个LinkedHashMap
Object ysCache = redisTemplate.opsForValue().get(ys.getName());
System.out.println(ysCache);

存对象集合结果一样…
redisTemplate.opsForValue().set("lol", students);
Object lolCache = redisTemplate.opsForValue().get("lol");
System.out.println(lolCache);

解决办法:
Jackson2JsonRedisSerializer序列化时 存数据都采用JSON字符串方式,然后取数据时也不直接将结果强转,而是使用JSON反序列化 将JSON字符串反序列化为java对象或集合
请看示例二:VALUE 存JSON字符串
结论:Jackson2JsonRedisSerializer序列化方式,如VALUE直接存对象或者对象集合,获取时结果为LinkedHashMap,无法直接使用JDK强转方法转为对象或对象集合,需借助工具进行转换为实体与实体集合
(2)VALUE 存JSON字符串
存:
redisTemplate.opsForValue().set(ys.getName(), JSON.toJSONString(ys));
redisTemplate.opsForValue().set(mw.getName(), JSON.toJSONString(mw));

–

字符串中有转义字符
取:
Object ysCache = redisTemplate.opsForValue().get(ys.getName());
// Student(name=亚索, age=122)
System.out.println(ysCache == null ? null : JSON.parseObject(ysCache.toString(), Student.class));
List<Object> cacheList = redisTemplate.opsForValue().multiGet(students.stream().map(Student::getName).collect(Collectors.toList()));
List<Student> studentList = cacheList.stream().filter(Objects::nonNull).map(Object::toString).map(x -> JSON.parseObject(x, Student.class)).collect(Collectors.toList());
// [Student(name=亚索, age=122), Student(name=蛮王, age=234)]
System.out.println(studentList);
结论:Jackson2JsonRedisSerializer序列化方式,VALUE存JSON字符串时,取值也为JSON字符串,需借助JSON工具进行转换为实体类或实体集合
(3)管道Pipelined存数据
存:
redisTemplate.executePipelined((RedisCallback<String>) conn -> {
students.forEach(s -> conn.set(s.getName().getBytes(), JSON.toJSONString(s).getBytes()));
return null;
});

–

取:
获取管道存储的值变为了LinkedHashMap

因为我们需要将map转为java对象,我这里采用的是先转JSON字符串方式


List<Object> cacheList = redisTemplate.opsForValue().multiGet(students.stream().map(Student::getName).collect(Collectors.toList()));
if (CollectionUtils.isEmpty(cacheList)) {
return null;
}
List<Student> studentList = cacheList.stream().filter(Objects::nonNull).map(JSON::toJSONString).map(x -> JSON.parseObject(x, Student.class)).collect(Collectors.toList());
// [Student(name=亚索, age=122), Student(name=蛮王, age=234)]
System.out.println(studentList);
结论:Jackson2JsonRedisSerializer 序列化方式,且使用管道操作后,获取的值也是一个linkedHashMap,需借助工具才可将值反序列化为实体对象或实体对象集合
边栏推荐
- MYSQL安装出现问题(The service already exists)
- Talk about the secret of high performance of message queue -- zero copy technology
- 「面试高频题」难度大 1.5/5,经典「前缀和 + 二分」运用题
- Cloud computing in my eyes - PAAS (platform as a service)
- Image transformation, transpose
- Redis安装部署(Windows/Linux)
- WSL installation, beautification, network agent and remote development
- Redis installation and deployment (windows/linux)
- 【Go实战基础】gin 如何绑定与使用 url 参数
- Right click menu of QT
猜你喜欢

别找了,Chrome浏览器必装插件都在这了

Solutions to Chinese garbled code in CMD window

机器学习实战:《美人鱼》属于爱情片还是动作片?KNN揭晓答案

京东面试官问:LEFT JOIN关联表中用ON还是WHERE跟条件有什么区别

MYSQL安装出现问题(The service already exists)

概率还不会的快看过来《统计学习方法》——第四章、朴素贝叶斯法

Chrome用户脚本管理器-Tampermonkey 油猴

C language implementation of mine sweeping game

C4D quick start tutorial - C4d mapping

How to realize asynchronous programming in a synchronous way?
随机推荐
Oracle delete tablespace and user
Use of libusb
Actual combat of microservices | discovery and invocation of original ecosystem implementation services
Microservice practice | load balancing component and source code analysis
Jingdong senior engineer has developed for ten years and compiled "core technology of 100 million traffic website architecture"
Redis sorted set data type API and application scenario analysis
Microservice practice | teach you to develop load balancing components hand in hand
Complete solution of servlet: inheritance relationship, life cycle, container, request forwarding and redirection, etc
[go practical basis] how to verify request parameters in gin
Sentinel reports failed to fetch metric connection timeout and connection rejection
Matplotlib swordsman Tour - an artist tutorial to accommodate all rivers
C language implementation of mine sweeping game
Gocv split color channel
Matplotlib swordsman - a stylist who can draw without tools and code
Gocv boundary fill
Matplotlib剑客行——没有工具用代码也能画图的造型师
[go practical basis] how to set the route in gin
C Baidu map, Gaode map, Google map (GPS) longitude and latitude conversion
C language - Blue Bridge Cup - 7 segment code
[staff] time mark and note duration (staff time mark | full note rest | half note rest | quarter note rest | eighth note rest | sixteenth note rest | thirty second note rest)