目录
序列化和反序列化在网络传输过程中需要做的事情。
序列化 就是得的 字节流,反序列化就是得的对象。
下面梳理Java编程需要用到的一些序列化技术。有些 序列化技术 不是简单的API调用,做了一些说明。其他一些简单的API调用只是提一下。
JDK原生的序列化
java.io.ObjectInputStream
java.io.ObjectOutputStream
字符串获取字节流
JDK的String 可以直接获取的 字节流 ,所以 最简单的就是 得到 字符串,比如Json字符串,直接调用 字符串的 getBytes方法 获取字节流。 那么也可以直接通过 String 的 构造方法 直接将字节流得的字符串
// 序列化
java.lang.String#getBytes()
// 反序列化
public String(byte bytes[], Charset charset) {
this(bytes, 0, bytes.length, charset);
}
Protobuf
使用 protobuf,首先需要创建 .proto 文件, 该文件 定义了 将 序列化的 结构 数据。
需要根据 规范 来创建 定义 .proto 文件,这个是首先需要 掌握的。
可以封装到公共的包来使用
步骤:
1. 创建 .proto 文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.wxj.grpctest.auto";
message RequestWxj {
string name = 1;
}
2. protoc 生成 代码 或者 maven 插件生成代码
3. 使用,比如 使用 proto文件 生成了一个RequestWxj,就可以来完成 数据的序列化反序列化
// 序列化 RequestWxj.newBuilder().build().toByteArray(); // 反序列化 RequestWxj.parseFrom(new byte[10]);
总结: protobuf 完成序列化和反序列化,就是 根据 .proto文件 生成了 目标 类文件,这个类文件 具有序列化和反序列化的功能,当然,是 protobuf 在生成类文件时 自动加上的功能,有了这些功能,就可以用这个类进行序列化和反序列化操作。
Protostuff
引入相关依赖
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.7.4</version> <!-- released at Apr 30, 2021 -->
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.7.4</version>
</dependency>
定义实体类,使用 @Tag 标记 字段
@Data @Builder
public class Persion {
@Tag(1)
private String name;
@Tag(2)
private int age;
}
序列化
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
Persion jack = Persion.builder().age(1).name("jack").build();
Schema<Persion> schema = RuntimeSchema.getSchema(Persion.class);
byte[] data = ProtobufIOUtil.toByteArray(jack, schema,buffer);
反序列化
Persion obj2 = Persion.builder().build();
Schema<Persion> schema2 = RuntimeSchema.getSchema(Persion.class);
ProtobufIOUtil.mergeFrom(data, obj2, schema);
protostuf序列化的结果 比 JSON 这种 序列化的结果 省空间
上述对象,protostuf 序列化结果占8个字节,JSON序列化结果占23个字节。
Thrift
官网
Thrift 应该不是专门用来完成序列化反序列化的,他提供的是 RPC 的服务,简单示例如下:
1. 需要安装 thrift 工具包软件,用来生成 代码,可在官网下载
2. 项目添加maven依赖
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.16.0</version>
</dependency>
3. 编写 .thrift文件
namespace java wxj.test.serializertest.thrift
struct MyPerson{
1:optional string userName;
}
service MyThriftService{
MyPerson hello(1:MyPerson myPerson);
}
4. 根据 .thrift 生成 代码
thrift-0.16.0.exe -o F:\code\src\main\java -gen java F:\code\src\main\java\wxj\test\serializertest\thrift\Persion.thrift
可以用 -help来查看 具体用法
5. 说明一下生产的代码 怎么来使用
服务端:
public class MyServer implements MyThriftService.Iface{
@Override
public MyPerson hello(MyPerson myPerson) throws TException {
System.out.println("MyServer exe :" + myPerson);
return myPerson;
}
}
服务端启动:
public static void main(String[] args) throws Exception{
TNonblockingServerSocket serverSocket =new TNonblockingServerSocket(8803);
THsHaServer.Args arg=new THsHaServer.Args(serverSocket).maxWorkerThreads(4).minWorkerThreads(2);
MyThriftService.Processor<MyServer> processor =new MyThriftService.Processor<>(new MyServer());
arg.protocolFactory(new TCompactProtocol.Factory());
arg.transportFactory(new TFastFramedTransport.Factory());
arg.processorFactory(new TProcessorFactory(processor));
TServer tServer = new THsHaServer(arg);
System.out.println("Running Simple Server");
tServer.serve();
客户端:
TTransport transport =null;
try {
transport = new TFramedTransport(new TSocket("127.0.0.1",8803),600);
TProtocol protocol = new TCompactProtocol(transport);
MyThriftService.Client client = new MyThriftService.Client(protocol);
transport.open();
MyPerson myPerson = new MyPerson();
myPerson.setUserName("jack");
MyPerson result = client.hello(myPerson);
} catch (TException e) {
e.printStackTrace();
} finally {
transport.close();
}
如果会使用 protobuf,那么 理解 thrift 也不难。 同样需要 自定义文件,同样需要根据自定义文件来生成代码,同样是使用生成的代码来完成具体功能。
kryo
hessian
fst
JSON字符串序列化
上面的几种序列化方式,是直接将字节流反序列化成不同的对象 或者 不同的对象 序列化成字节流。
序列化工具 JSON 指的是能够帮助开发者将内存中的数据对象转换为 JSON 格式的字符串(序列化),或将 JSON 字符串反向转换为内存中的数据对象(反序列化)的软件库。
Gson: 谷歌提供的一个用来在 Java 对象和 JSON 数据之间进行映射的库。
Jackson: 功能强大、性能优秀的 Java JSON 处理库,支持数据绑定和流式处理。
Fastjson: 阿里巴巴开源的 Java 语言的 JSON 处理库,以其快速和便捷著称。
Jackson
Fasterxml 是一个与开源项目相关的组织,最著名的是其旗下的 Jackson 项目系列,这是一个广泛使用的 Java 库,专注于 JSON 处理(序列化和反序列化)。Jackson 包含多个模块,其中最核心的是 jackson-databind,它允许Java对象与JSON格式之间的相互转换,极大地简化了数据交换过程。
Jackson 主要有以下几个关键部分:
Jackson Core (jackson-core): 提供基本的 streaming API(JsonParser 和 JsonGenerator)用于读写 JSON 数据。
Jackson Data Binding (jackson-databind): 基于 Core 扩展,实现了对象到 JSON 的自动映射,允许直接将 Java 对象转换为 JSON 字符串,或者反过来,无需手动编写解析或生成代码。
Jackson Annotations (jackson-annotations): 提供了一套注解,用于控制序列化和反序列化的行为,如忽略某些字段、指定日期格式等。
pom.xml 依赖
这个依赖会自动引入另外两个模块的依赖包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
<scope>compile</scope>
</dependency>
使用
// 核心代码
ObjectMapper objectMapper = new ObjectMapper();
// 序列化
objectMapper.writeValueAsBytes(t);
// 反序列化
objectMapper.readValue
Gson
Gson 是 Google 开源的一个 Java 库,用于将 Java 对象转换成 JSON 字符串,或者将 JSON 字符串转换成等价的 Java 对象
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
Gson gson = new Gson();
// 序列化
String jsonString = gson.toJson(user);// 反序列化
User user = gson.fromJson(jsonString, User.class);
FastJson
Fastjson 是阿里巴巴开源的一个高性能的 Java 语言的 JSON 库。它具有极快的性能,广泛应用于互联网公司和商业产品的生产环境。Fastjson 的主要特点包括快速的 JSON 序列化及反序列化、便捷的操作 JSON 数据、支持泛型、支持 JDK8 的新特性等。下面通过示例来说明 Fastjson 如何使用。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
JSON.toJSONString(user) ;
JSON.parseObject(jsonString, User.class);