一文彻底搞懂序列化和反序列化

打印 上一主题 下一主题

主题 865|帖子 865|积分 2595

背景

近来项目中要按照对象方式举行存取,使用时再拿出来,于是我们就要学习序列化和反序列化的相关知识。
基于我们的项目,按照课表举行推课的时候,课表中当前课程结束的时候,将实行的颗粒存到redis中。
序列化是将对象转换为字节流的一种方式,与之对应的是反序列化,将二进制流转为对象的一种情势。
由于序列化会将对象的状态信息转换为字节流,如许就可以将对象写入文件,保存到数据库大概是举行网络传输发送到另外一个系统,如许可以达即使在不同的情况大概系统重,只要可以读取这些字节流就可以构建出与初始对象状态完全雷同的对象。
在项目中我显式使用序列化的方式是我在后端controller返回实体类都实现了 Serializable 接口,如许就可以实现正常的网络传输,http协议是基于文本传输的,所以我后端想要往前端传数据,就要将对象转换为文本格式(JSON 大概 XML)才能发给前端,前端才能辨认,这个过程就涉及到了序列化。还有一个应用场景是我们在推课过程中,当课暂停的时候,我们需要记录好当前暂停的颗粒位置,并将其存到redis中,这里也是涉及到一个序列化的问题,将内存的颗粒对象通过序列化以后转为json存到redis中,下次继续推这个课的时候再通过反序列化的方式从库里边拿出对应的颗粒。
当我在真正使用的时候可以直接让当前实体类去实现Serializable 接口,当我想只序列化某个字段的时候可以使用 @JsonSerialize 注解 ,注解后可以添加参数指定序列化的格式,大概我不想序列化某个字段的时候使用@JSONField(serialize = false) 注解。
步骤

概念

序列化和反序列化是计算机科学中用于数据存储和传输的重要概念。
序列化(Serialization)

是将数据结构或对象转换成一种可存储或可传输格式的过程。在序列化后,数据可以被写入文件、发送到网络或存储在数据库中,以便在需要时可以再次还原成原始的数据结构或对象。序列化的过程通常涉及将数据转换成字节流或雷同的格式,使其能够在不同平台和编程语言之间举行传输和交换。
反序列化(Deserialization)

是序列化的逆过程,即将序列化后的数据重新还原成原始的数据结构或对象。反序列化是从文件、网络数据或数据库中读取序列化的数据,并将其转换回原始情势,以便在步伐中举行使用和操作。
使用场景

序列化和反序列化在很多场景中都非常有效,比方:
数据存储:将步伐中的数据保存到文件或数据库中,以便在以后重新加载和使用。
网络通讯:在网络上传输数据时,需要将数据序列化为字节流,以便在吸收端举行反序列化。
分布式系统:在分布式系统中,不同计算节点之间需要通过序列化和反序列化来交换数据。
历程间通讯:不同历程之间通讯时,数据需要在序列化和反序列化之间举行转换。
常见的序列化格式包罗 JSON(JavaScript Object Notation)、XML(eXtensible Markup Language)、Protocol Buffers、MessagePack等。每种格式有其优势和实用场景,选择符合的序列化格式取决于详细的应用需求。
明白原理小Demo(可以明白成编码解码,很简单的)

  1. import java.io.*;
  2. public class Serialization {
  3.     private static final File SAVE_FILE = new File("D:" + File.separator + "demo.Class");
  4.     public static void saveObject(Object object) throws IOException {
  5.         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
  6.         oos.writeObject(object); // 序列化
  7.         oos.close();
  8.     }
  9.     public static Object loadObject() throws Exception {
  10.         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
  11.         Object obj = ois.readObject(); // 反序列化
  12.         ois.close();
  13.         return obj;
  14.     }
  15.     public static void main(String[] args) throws Exception {
  16.         saveObject(new Class(new Person("p",11),"class",12));// 序列化
  17.         Class c = (Class)loadObject();
  18.         System.out.println(c); // 反序列化
  19.     }
  20.     public static class Person implements Serializable {
  21.         private String name;
  22.         private int age;
  23.         public String getName() {
  24.             return name;
  25.         }
  26.         public void setName(String name) {
  27.             this.name = name;
  28.         }
  29.         public int getAge() {
  30.             return age;
  31.         }
  32.         public void setAge(int age) {
  33.             this.age = age;
  34.         }
  35.         public Person(String name, int age) {
  36.             this.name = name;
  37.             this.age = age;
  38.         }
  39.         @Override
  40.         public String toString() {
  41.             return "Person{" +
  42.                     "name='" + name + '\'' +
  43.                     ", age=" + age +
  44.                     '}';
  45.         }
  46.     }
  47.     public static class Class implements Serializable{
  48.         private Person person;
  49.         private String name;
  50.         private int age;
  51.         public Person getPerson() {
  52.             return person;
  53.         }
  54.         public void setPerson(Person person) {
  55.             this.person = person;
  56.         }
  57.         public String getName() {
  58.             return name;
  59.         }
  60.         public void setName(String name) {
  61.             this.name = name;
  62.         }
  63.         public int getAge() {
  64.             return age;
  65.         }
  66.         public void setAge(int age) {
  67.             this.age = age;
  68.         }
  69.         @Override
  70.         public String toString() {
  71.             return "Class{" +
  72.                     "person=" + person +
  73.                     ", name='" + name + '\'' +
  74.                     ", age=" + age +
  75.                     '}';
  76.         }
  77.         public Class(Person person) {
  78.             this.person = person;
  79.         }
  80.         public Class(Person person, String name, int age) {
  81.             this.person = person;
  82.             this.name = name;
  83.             this.age = age;
  84.         }
  85.     }
  86. }
复制代码
可以通过打断点的方式检察对象的展示情况
将内存中的对象通过序列化的方式存储到当地的某个文件中

然后调用另外一个方法从当地文件中拿到对象放置到内存中


如许我们就了解了序列化和反序列的概念,下面看看在redis是怎样实现序列化和反序列化的吧。
使用redis步骤

建立springboot项目
引入坐标
  1.        <dependency>
  2.             <groupId>org.springframework.boot</groupId>
  3.             <artifactId>spring-boot-starter-data-redis</artifactId>
  4.         </dependency>
复制代码
建类

  1. 在这里插入代码片
复制代码
  1. package com.example.redis.config;
  2. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  3. import com.fasterxml.jackson.annotation.PropertyAccessor;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  8. import org.springframework.data.redis.core.RedisTemplate;
  9. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  10. import org.springframework.data.redis.serializer.RedisSerializer;
  11. import org.springframework.data.redis.serializer.StringRedisSerializer;
  12. @Configuration
  13. public class RedisConfig {
  14.     /**
  15.      * RedisTemplate配置
  16.      */
  17.     @Bean
  18.     public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
  19.         // 设置序列化
  20.         Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
  21.         ObjectMapper om = new ObjectMapper();
  22.         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  23.         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  24.         jackson2JsonRedisSerializer.setObjectMapper(om);
  25.         // 配置redisTemplate
  26.         RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
  27.         redisTemplate.setConnectionFactory(lettuceConnectionFactory);
  28.         RedisSerializer<?> stringSerializer = new StringRedisSerializer();
  29.         // key序列化
  30.         redisTemplate.setKeySerializer(stringSerializer);
  31.         // value序列化
  32.         redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
  33.         // Hash key序列化
  34.         redisTemplate.setHashKeySerializer(stringSerializer);
  35.         // Hash value序列化
  36.         redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
  37.         redisTemplate.afterPropertiesSet();
  38.         return redisTemplate;
  39.     }
  40. }
复制代码
  1. server:
  2.   port: 8081
  3. spring:
  4.   redis:
  5.     host: **redis.***d.tech
  6.     port: 6379
  7.     password: ***
  8.     database: 0
  9.     timeout: 300000ms  #连接超时
  10.     jedis:
  11.       pool:
  12.         max-active: 8  #连接池最大的连接数
  13.         max-wait: -1ms  #连接池最大的阻塞等待时间(负值表示没有限制)
  14.         max-idle: 500  #连接池最大的空闲连接
复制代码
  1. package com.example.redis.Entity;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. import java.util.Date;
  5. @Data
  6. public class UserInfo implements Serializable {
  7.     /**
  8.      * id
  9.      */
  10.     private Integer id;
  11.     /**
  12.      * 姓名
  13.      */
  14.     private String name;
  15.     /**
  16.      * 创建时间
  17.      */
  18.     private Date createTime;
  19. }
复制代码
  1. package com.example.redis.utils;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.data.redis.core.RedisTemplate;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.util.StringUtils;
  7. /**
  8. * @ClassName RedisUtils
  9. * @Description
  10. * @Author Lizhou
  11. * @Date 2020-10-22 10:10:10
  12. **/
  13. @Slf4j
  14. @Component
  15. public class RedisUtils {
  16.     @Autowired
  17.     private RedisTemplate<String, Object> redisTemplate;
  18.     /**
  19.      * 根据key读取数据
  20.      */
  21.     public Object get(final String key) {
  22.         if (StringUtils.isEmpty(key)) {
  23.             return null;
  24.         }
  25.         try {
  26.             return redisTemplate.opsForValue().get(key);
  27.         } catch (Exception e) {
  28.             e.printStackTrace();
  29.         }
  30.         return null;
  31.     }
  32.     /**
  33.      * 写入数据
  34.      */
  35.     public boolean set(final String key, Object value) {
  36.         if (StringUtils.isEmpty(key)) {
  37.             return false;
  38.         }
  39.         try {
  40.             redisTemplate.opsForValue().set(key, value);
  41.             log.info("存入redis成功,key:{},value:{}", key, value);
  42.             return true;
  43.         } catch (Exception e) {
  44.             log.error("存入redis失败,key:{},value:{}", key, value);
  45.             e.printStackTrace();
  46.         }
  47.         return false;
  48.     }
  49. }
复制代码
  1. package com.example.redis;
  2. import com.example.redis.Entity.UserInfo;
  3. import com.example.redis.utils.RedisUtils;
  4. import org.junit.jupiter.api.Test;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import java.util.Date;
  8. @SpringBootTest
  9. class RedisTestApplicationTests {
  10.     @Autowired
  11.     private RedisUtils redisUtil;
  12.     @Test
  13.     void contextLoads() {
  14.         UserInfo userInfo = new UserInfo();
  15.         userInfo.setId(1);
  16.         userInfo.setName("jack");
  17.         userInfo.setCreateTime(new Date());
  18.         // 放入redis
  19.         redisUtil.set("user", userInfo);
  20.         // 从redis中获取
  21.         System.out.println("获取到数据:" + redisUtil.get("user"));
  22.     }
  23. }
复制代码

根据key值检察redis中的值

简单先容redis

Redis(Remote Dictionary Server)是一种开源的高性能键值存储数据库,它也被称为数据结构服务器,因为它支持多种机动的数据结构。Redis以内存中的数据结构为基础,提供了快速、高效的数据存储和访问能力。它可以用作数据库、缓存、消息代理和排行榜等多种用途。
以下是 Redis 的一些重要特点:
键值存储:
Redis将数据存储为键值对,此中键是唯一的标识符,而值可以是字符串、哈希、列表、集合、有序集合等各种数据结构。
内存数据库:(因为我们是面向对象开发,全部就要使用内存数据库啦,因为要把对象存取来哦)
Redis的全部数据都存储在内存中,因此具有非常快的读写速度。但是,它也支持将数据长期化到磁盘,以便在重启后规复数据。
丰富的数据结构:
Redis支持多种数据结构,如字符串、哈希表、列表(链表)、集合、有序集合等。这使得Redis在处置惩罚不同类型的数据时非常机动和高效。
高性能:
由于数据存储在内存中,Redis能够实现非常高的读写速度。别的,它使用单线程模型来避免了多线程带来的竞争条件,使得其在单核系统上也能表现出色。
支持事务:
Redis支持简单的事务,你可以将多个命令放在一个事务中,然后一次性实行这些命令。在事务实行期间,其他客户端不会对其举行干扰。
发布/订阅:
Redis支持发布/订阅模式,允许客户端订阅一个或多个频道,当有消息发布到这些频道时,订阅的客户端将会收到相应的消息。
集群支持:
Redis支持将数据分布在多个节点上,从而实现高可用性和横向扩展。
轻量级:
Redis的代码库相对较小,没有复杂的依赖,因此非常轻量级且易于安装和摆设。
Redis广泛应用于Web开发、缓存、会话存储、及时分析、消息队列等场景。由于其高性能和机动性,Redis成为了很多应用架构中不可或缺的一部门。
总结

序列化在Redis中发挥偏重要的作用,它使得数据可以被转换成一种便于存储和传输的格式,并可以通过网络举行传输。当数据需要被存储到Redis中时,通常需要先举行序列化,将数据转换成得当Redis存储的情势。而在从Redis中取出数据时,则需要举行反序列化,将序列化后的数据重新还原成原始的数据结构,以便在步伐中举行使用和操作。
总之,序列化和反序列化是数据在存储和传输过程中的桥梁,而Redis作为高性能的键值存储数据库,则使用序列化机制来存储和操作数据,提供快速、机动的数据存储和访问服务。通过将数据序列化后存储在Redis中,我们可以充分发挥Redis的优势,实现高效的数据处置惩罚和管理。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表