Java序列化案例demo(包含Kryo、JDK原生、Protobuf、ProtoStuff以及hessian)(二)

简介: Java序列化案例demo(包含Kryo、JDK原生、Protobuf、ProtoStuff以及hessian)(二)

三、Protobuf序列化


介绍

protobuf—Github地址、protobuf-java


介绍:Protobuf 出自于 Google,性能还比较优秀,也支持多种语言,同时还是跨平台的。就是在使用中过于繁琐,因为你需要自己定义 IDL 文件和生成对应的序列化代码。这样虽然不然灵活,但是,另一方面导致 protobuf 没有序列化漏洞的风险。


Protobuf 包含序列化格式的定义、各种语言的库以及一个 IDL 编译器。正常情况下你需要定义 proto 文件,然后使用 IDL 编译器编译成你需要的语言。


正常流程:定义proto文件 -> 使用proto编译工具编译得到Java类 -> 使用该类来进行序列化与反序列化。


快速开始

引入依赖


<!--      protobuf  -->
<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.21.1</version>
</dependency>


使用步骤


1、首先安装proto的转换工具


下载地址



安装配置好对应的path路径,测试下命令:


protoc --version


安装这个proto工具的目的是将对应自己编写的.proto文件转为一个Java类,使用这个Java类即可进行序列化与反序列化。


在一个.proto文件中可以写多个结构体都是可以的。


2、编写proto文件


使用ProtoBuf序列化数据—可查看对应protobuf对应java的类型


syntax = "proto3";
option java_package = "com.changlu.serialize.protobuf";
option java_outer_classname = "DemoModel";
message User {
  string name = 1;
  uint32 age = 2;
}
message Message {
  uint32 message_type = 1;
}


java_package:表示目标生成的包名路径。

java_outer_classname:目标生成的工具类名称。

说明:若是觉得自己编写比较麻烦,那么我们可以自己先定义Java实体类,然后使用IDEA的插件将这个实体类转为对应proto的struct类型。


插件名称:pojo to proto;protobuf插件安装使用


3、准备好proto文件了之后,我们就要开始生成对应的工具类了


当前路径在main/proto/xxx下,我们想要输出到对应的main/java/com/changlu/serialize/protobuf/xxx中:



接着我们输入命令:


# -I:我自己编写的.proto 文件的位置。 
# --java out 输出位置会以完整包名的形式出输出,我指定的是上级目录的java中,此时配合proto文件里的com.changlu.xxx,即可输出到我想要的目录下
# ./subscribeReq.proto:当前需要编译成java的proto文件名。
protoc -I=./ --java_out=../java ./User.proto



ok,此时我们就有了这个工具类DemoModel,对应的User、Message的实体类都在这个DemoModel类中有了,对于序列化与反序列化操作也在这个DemoModel中进行。


测试



//测试ProtoBuf
testProtobufSerialzize();


public void testProtobufSerialzize(){
    //准备实体类
    DemoModel.User.Builder userBuilder = DemoModel.User.newBuilder();
    userBuilder.setAge(18);
    userBuilder.setName("changlu");
    DemoModel.User user = userBuilder.build();
    System.out.println("=====开始序列化:Protobuf=====");
    System.out.println("开始进行序列化");
    long startTime = System.nanoTime();
    //序列化
    byte[] data = user.toByteArray();
    long endTime = System.nanoTime();
    System.out.println("  序列化时间为:" + (endTime - startTime) / 1000000000.0 + "秒");
    System.out.println("  序列化后的内容为:" + new String(data));
    System.out.println("  序列化后的长度为:" + data.length);
    System.out.println("开始进行反序列化");
    startTime = System.nanoTime();
    //反序列化
    try {
        System.out.println("  反序列化后得到的对象为:" + DemoModel.User.parseFrom(data));
    } catch (InvalidProtocolBufferException e) {
        throw new RuntimeException("Serialization failed");
    }
    endTime = System.nanoTime();
    System.out.println("  反序列化时间为:" + (endTime - startTime) / 1000000000.0 + "秒");
    System.out.println("=====结束序列化:Protobuf=====" + "\n");
}




四、ProtoStuff


介绍

protostuff-github


由于 Protobuf 的易用性,它的哥哥 Protostuff 诞生了。


protostuff 基于 Google protobuf,但是提供了更多的功能和更简易的用法。虽然更加易用,但是不代表 ProtoStuff 性能更差。


快速开始
<!--      protobufstuff  -->
<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-core</artifactId>
    <version>1.7.4</version>
</dependency>
<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-runtime</artifactId>
    <version>1.7.4</version>
</dependency>
<!--      protobufstuff  -->



package com.changlu.serialize;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
/**
 * @Description: ProtoStuffSer序列化工具
 * @Author: changlu
 * @Date: 11:33 AM
 */
public class ProtoStuffSerializer implements Serializer{
    //DEFAULT_BUFFER_SIZE:512
    //每次序列化时使用缓冲区
    private static final LinkedBuffer BUFFER = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
    public byte[] serialize(Object obj) {
        Class<?> clazz = obj.getClass();
        Schema schema = RuntimeSchema.getSchema(clazz);
        byte[] bytes;
        try {
            //序列化
            bytes = ProtostuffIOUtil.toByteArray(obj, schema, BUFFER);
        }finally {
            BUFFER.clear();
        }
        return bytes;
    }
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
        Schema<T> schema = RuntimeSchema.getSchema(clazz);
        //反序列化
        T obj = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
        return obj;
    }
}



测试



//测试ProtoStuff
testSerialize(new ProtoStuffSerializer(), rpcResponse);



说明:这个序列化算法的反序列化是最快的目前来看。


五、hessian


介绍

hessian 是一个轻量级的,自定义描述的二进制 RPC 协议。hessian 是一个比较老的序列化实现了,并且同样也是跨语言的。


dubbo RPC 默认启用的序列化方式是 hessian2 ,但是,Dubbo 对 hessian2 进行了修改,不过大体结构还是差不多。


快速开始
<!--      hessian  -->
<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.65</version>
</dependency>



package com.changlu.serialize;
import com.caucho.hessian.io.HessianInput;
import com.caucho.hessian.io.HessianOutput;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
 * @Description: Hessian序列化
 * @Author: changlu
 * @Date: 12:38 PM
 */
public class HessianSerializer implements Serializer{
    @Override
    public byte[] serialize(Object obj) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();){
            HessianOutput hessianOutput = new HessianOutput(baos);
            //序列化
            hessianOutput.writeObject(obj);
            return baos.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("Serialization failed");
        }
    }
    @Override
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);){
            HessianInput hessianInput = new HessianInput(bais);
            //反序列化
            return clazz.cast(hessianInput.readObject(clazz));
        } catch (IOException e) {
            throw new RuntimeException("Serialization failed");
        }
    }
}



测试



//测试Hession
testSerialize(new HessianSerializer(), rpcResponse);



总结


Kryo 是专门针对 Java 语言序列化方式并且性能非常好,如果你的应用是专门针对 Java 语言的话可以考虑使用,并且 Dubbo 官网的一篇文章中提到说推荐使用 Kryo 作为生产环境的序列化方式。


其他跨语言的序列化方式包含:Protobuf、 ProtoStuff、hessian如果有跨语言需求的话可以考虑使用,其他还包含Thrift,Avro 这些。

相关文章
|
11天前
|
存储 Ubuntu Java
【Linux】已解决:Ubuntu虚拟机安装Java/JDK
【Linux】已解决:Ubuntu虚拟机安装Java/JDK
20 1
|
14天前
|
JavaScript 前端开发 Java
Java数字化产科管理系统源码,多家医院应用案例,可直接上项目
Java开发的数字化产科管理系统,已在多家医院实施,支持直接部署。系统涵盖孕产全程,包括门诊、住院、统计和移动服务,整合高危管理、智能提醒、档案追踪等功能,与HIS等系统对接。采用前后端分离架构,Java语言,Vue前端,若依框架,MySQL数据库。优势在于提升就诊效率,降低漏检率,自动报表生成,减少重复工作,支持数据研究,并实现医院与卫计委平台的数据互通,打造全生育周期健康服务。
28 4
|
16天前
|
算法 Java 编译器
Java基础之lambda表达式(JDK1.8新特性)
Java基础之lambda表达式(JDK1.8新特性)
20 1
|
21天前
|
Java 编译器
Java健壮性 Java可移植性 JDK, JRE, JVM三者关系 Java的加载与执行原理 javac编译与JAVA_HOME环境变量介绍 Java中的注释与缩进 main方法的args参数
Java健壮性 Java可移植性 JDK, JRE, JVM三者关系 Java的加载与执行原理 javac编译与JAVA_HOME环境变量介绍 Java中的注释与缩进 main方法的args参数
20 1
|
9天前
|
存储 安全 Java
Java面试题:请解释Java中的泛型集合框架?以及泛型的经典应用案例
Java面试题:请解释Java中的泛型集合框架?以及泛型的经典应用案例
15 0
|
16天前
|
Java API 数据处理
Java JDK 8新特性详解及应用实例
Java JDK 8新特性详解及应用实例
|
17天前
|
机器学习/深度学习 人工智能 自然语言处理
Java中的自然语言处理应用案例分析
Java中的自然语言处理应用案例分析
|
17天前
|
负载均衡 Java 微服务
Java中的可扩展微服务架构设计案例解析
Java中的可扩展微服务架构设计案例解析
|
Java
synchronized【Java】中使用的demo
synchronized【Java】中使用的demo
129 1
synchronized【Java】中使用的demo
|
8天前
|
Java 调度
Java线程的六种状态
Java线程有六种状态: 初始(NEW)、运行(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)、终止(TERMINATED)。
26 1