长春专业网站建设价格成功的电商网站
2026/1/15 5:27:41 网站建设 项目流程
长春专业网站建设价格,成功的电商网站,asp 建站,页面跳转快捷键有位读者问了#xff0c;我这么一个问题#xff1a; 不管是 RPC 或者 HTTP#xff0c;只要传输的内容是「对象」#xff0c;要想在接收方还原出一摸一样的「对象」#xff0c;那就需要序列化和反序列化。 那什么是序列化和反序列化呢#xff1f; RPC 能帮助我们的应用透明…有位读者问了我这么一个问题不管是 RPC 或者 HTTP只要传输的内容是「对象」要想在接收方还原出一摸一样的「对象」那就需要序列化和反序列化。那什么是序列化和反序列化呢RPC 能帮助我们的应用透明地完成远程调用即调用其他服务器的函数就像调用本地方法一样。发起调用请求的那一方叫做调用方被调用的一方叫做服务提供方。调用方和服务提供方一般是不同的服务器所以就需要通过网络来传输数据并且 RPC 常用于业务系统之间的数据交互需要保证其可靠性所以 RPC 一般默认采用 TCP 协议来传输。同时 HTTP 协议也是建立在 TCP 之上的。网络传输的数据必须是二进制数据但调用方请求的出入参数都是对象而对象是肯定没法直接在网络中传输的需要提前把「对象转成二进制数据」进行网络传输这个转换过程就做序列化。相反服务提供方收到网络数据后需要将「二进制数据转成对象」这个转换过程就叫做反序列化。总结来说序列化就是将对象转换成二进制数据的过程以方便传输或存储。而反序列就是将二进制转换为对象的过程。为什么 RPC 经常提到序列化呢因为网络传输的数据必须是二进制数据所以在 RPC 调用中对入参对象与返回值对象进行序列化与反序列化是一个必须的过程。HTTP 什么时候需要序列化呢举个例子。当客户端和服务端交互的数据是 JSON这时候发送方需要将 JSON 对象转换成二进制数据发送到网络接收方需要将接收到的二进制数据转换成 JSON 对象。说了这么多概念接下来跟大家说说有哪些常用的序列化方式JDK 原生序列化Java 语言中 JDK 就自带有序列化的方式举个 JDK 序列化的例子。注意这个例子是将 Student 对象保存到文件保存到文件的数据是二进制数据所以并不是说序列化只用在网络传输场景里只要是保存数据的场景只能是二进制数据时就需要用序列化。import java.io.*; public class Student implements Serializable { //学号 private int no; //姓名 private String name; public int getNo() { return no; } public void setNo(int no) { this.no no; } public String getName() { return name; } public void setName(String name) { this.name name; } Override public String toString() { return Student{ no no , name name \ }; } public static void main(String[] args) throws IOException, ClassNotFoundException { String basePath /root; FileOutputStream fos new FileOutputStream(basePath student.dat); //初始化一个学生对象 Student student new Student(); student.setNo(1); student.setName(xiaolin); //将学生对象序列化到文件里 ObjectOutputStream oos new ObjectOutputStream(fos); oos.writeObject(student); oos.flush(); oos.close(); //读取文件中的二进制数据并将数据反序列化为学生对象 FileInputStream fis new FileInputStream(basePath student.dat); ObjectInputStream ois new ObjectInputStream(fis); Student deStudent (Student) ois.readObject(); ois.close(); System.out.println(deStudent); } }从上面的代码我们可以知道JDK 自带的序列化具体的实现是由 ObjectOutputStream 完成的而反序列化的具体实现是由 ObjectInputStream 完成的。既然序列化是将对象转换为二进制数据那序列化的过程的二进制数据肯定是有某种固定的格式。比如 JDK 自带的序列化的过程如下图序列化过程就是在读取对象数据的时候不断加入一些特殊分隔符这些特殊分隔符用于在反序列化过程中截断用。头部数据用来声明序列化协议、序列化版本用于高低版本向后兼容对象数据主要包括类名、签名、属性名、属性类型及属性值当然还有开头结尾等数据除了属性值属于真正的对象值其他都是为了反序列化用的元数据存在对象引用、继承的情况下就是递归遍历“写对象”逻辑所以从这个例子我们可以知道任何一种序列化的方式其核心思想就要设计一套将对象转换成某种特定格式的二进制数据接着反序列化的时候就能根据规则从二进制数据解析出对象。这么看序列化其实就是一种协议序列化方和反序列化方都要遵循相同的规则否则就无法得到正常的数据。不过JDK 原生序列化缺陷就是不能跨语言只能在 Java 生态里使用。JSONJSON 数据的格式相信大家都很熟悉了吧在 Web 应用里特别常见通常后端和前端的耦合就是 JSON 数据。JSON 是典型的 Key-Value 方式没有数据类型。很多语言都实现了 JSON 序列化的第三库所以 JSON 序列化的方式可以跨语言。比如Java 语言中常用的 JSON 第三方类库有Gson: 谷歌开发的 JSON 库功能十分全面。FastJson: 阿里巴巴开发的 JSON 库性能十分优秀。Jackson: 社区十分活跃且更新速度很快。我这里说个 C 的 JSON 第三方库JSON for Modern C。使用起来很方便仅需要包含一个头文件“json.hpp”没有外部依赖也不需要额外的安装、编译、链接工作适合快速上手开发。因为 JSON 是 Key-Value 形式所以 JSON for Modern C 的操作和标准容器 map 一样用关联数组的“[]”来添加任意数据。这里贴几个例子// 给 JSON for Modern C 的 json 类取个别名 using json_t nlohmann::json; // JSON对象 json_t j; // age:18 j[age] 18; // name:xiaolin j[name] xiaolin; // gear:{suits:2099} j[gear][suits] 2099; // jobs:[superhero] j[jobs] {superhero}; vectorint v {1,2,3}; // numbers:[1,2,3] j[numbers] v; mapstring, int m {{one, 1}, {two, 2}}; // kv:{one:1,two:2} j[kv] m;添加完 JSON 数据后就可以调用成员函数 dump() 进行初始化得到 JSON 文本形式也就是 JSON 字符串cout j.dump() endl;反序列化也很简单只要调用静态成员函数 parse() 就行直接得到 JSON 对象// JSON文本原始字符串 string jsonStr R({ name: xiaolin, age : 18 }); // 从字符串反序列化 json_t j json_t::parse(jsonStr); // 验证序列化是否正确 assert(j[age] 18); assert(j[name] xiaolin);对于通常的应用来说掌握了基本的序列化和反序列化就够用了如果想要了解 JSON for Modern C 其他特性可以去看它的 Github。JSON 进行序列化存在的问题因为 JSON 进行序列化的额外空间开销比较大对于大数据量服务这意味着需要巨大的内存和磁盘开销所以如果在传输数据量比较小的场景就可以采用 JSON 序列化的方式。ProtoBufferProtoBuf 是由 Google 出品的是一种轻便、高效的结构化数据存储格式可以用于结构化数据序列化支持 Java、Python、C、Go 等语言。Protobuf 使用的时候必须写一个 IDLInterface description language文件在里面定义好数据结构只有预先定义了的数据结构才能被序列化和反序列化。下面是一个简单的 IDl 文件格式syntax proto2; // 使用第2版 package sample; // 定义名字空间 message Person { // 定义消息 required string name 1; // required表示必须字段 required int32 id 2; optional string email 3; // optional字段可以没有 }写完 IDL 文件后然后使用不同语言的 IDL 编译器生成序列化工具类。Protobuf 在 Github 有文档介绍了不同语言是怎么使用编译器生成序列化工具类了我在这里就不介绍了。这里贴 C 和 Java 语言使用 Protobuf 相关接口进行序列化和反序列化的例子。C 进行序列化和反序列化的例子// 类型别名 using person_t sample::Person; // 声明一个Protobuf对象 person_t p; // 设置每个字段的值 p.set_id(1); p.set_name(xiaolin); p.set_email(xiaolincoding163.com); // 序列化到字符串 string enc; p.SerializeToString(enc); // 反序列化 person_t p2; p2.ParseFromString(enc);Java 进行序列化和反序列化的例子/** * * // IDl 文件格式 * synax proto3; * option java_package com.test; * option java_outer_classname StudentProtobuf; * * message StudentMsg { * //序号 * int32 no 1; * //姓名 * string name 2; * } * */ StudentProtobuf.StudentMsg.Builder builder StudentProtobuf.StudentMsg.newBuilder(); builder.setNo(1); builder.setName(xiaolin); //把student对象转化为byte数组 StudentProtobuf.StudentMsg msg builder.build(); byte[] data msg.toByteArray(); //把刚才序列化出来的byte数组转化为student对象 StudentProtobuf.StudentMsg deStudent StudentProtobuf.StudentMsg.parseFrom(data); System.out.println(deStudent);现在很多大厂都在使用 Protobuf而且 gRPC 就是基于 Protobuf 来做的序列化。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询