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月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
572 1
|
11月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
497 1
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
800 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
1145 1
|
安全 Java API
Java最新技术(JDK 11+) 及以上 Java 最新技术之集合框架实操应用详解
本示例基于Java最新技术(JDK 11+),涵盖集合框架的核心功能,结合Java 8+特性(如Stream API、Lambda表达式)与并发编程最佳实践。内容包括:List操作(初始化、Lambda过滤、Stream处理)、Map操作(流式过滤、ConcurrentHashMap原子操作、并行流)、Set操作(TreeSet排序、CopyOnWriteArraySet并发安全)、Queue/Deque操作(优先队列、双端队列)以及高级聚合操作(集合转换、分组统计、平均值计算)。 [代码下载](https://pan.quark.cn/s/14fcf913bae6)
299 4
|
JSON Java 数据库连接
|
Oracle Java 关系型数据库
新手必看:Java 开发环境搭建之 JDK 与 Maven
本文分享了 Java 学习中 JDK 安装配置与 Maven 使用的入门知识,涵盖 JDK 下载安装、环境变量设置、Maven 安装配置及本地仓库与镜像设置,帮助新手快速搭建 Java 开发环境。
1831 0
|
存储 安全 Java
深入理解Java序列化接口及其实现机制
记住,序列化不仅仅是把对象状态保存下来那么简单,它涉及到类的版本控制、安全性和性能等多个重要方面。正确理解和实现Java序列化机制对于构建高效、安全和可维护的Java应用至关重要。
410 0
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
606 0
探索Java动态代理的奥秘:JDK vs CGLIB