Java的序列化是在文件传输中必不可少的一部分。常用的Java序列化机制有Java默认的序列化机制,谷歌的protobuf等。而Java默认的序列化机制效率太低,protobuf要写protostuff文件,又很麻烦,所以我这篇文章要介绍的就是——protostuff.
1、protostuff简介
在序列化文件不超过10M的时候最好还是使用Java自带的序列化机制。文件较大的时候用protostuff传输更好。
protostuff也是谷歌的产品旗下的,它是从谷歌的protobuf而来的,相对于protobuf提供了更多的功能和更简易的用法。
2、使用protostuff
(1)添加依赖
这里用maven,直接添加依赖。如果你没有maven,在百度上搜索相应的jar包就好了。

    <!--引入protostuff依赖--><dependency><groupId>io.protostuff</groupId><artifactId>protostuff-core</artifactId><version>1.6.0</version></dependency><dependency><groupId>io.protostuff</groupId><artifactId>protostuff-runtime</artifactId><version>1.6.0</version></dependency>

(2)定义要序列化的Bean
可以用注解等方式,这里就不再详细给出Bean的定义及实例化,详情可跳往Spring简述一
(3)

package org.boot.protostuff.util;import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;public class ProtostuffUtils {/*** 避免每次序列化都重新申请Buffer空间*/private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);/*** 缓存Schema*/private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<>();// 序列化方法,把指定对象序列化成字节数组@SuppressWarnings("unchecked")public static <T> byte[] serialize(T obj) {Class<T> clazz = (Class<T>) obj.getClass();Schema<T> schema = getSchema(clazz);byte[] data;try {data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);} finally {buffer.clear();}return data;}//反序列化方法,将字节数组反序列化成指定Class类型public static <T> T deserialize(byte[] data, Class<T> clazz) {Schema<T> schema = getSchema(clazz);T obj = schema.newMessage();ProtostuffIOUtil.mergeFrom(data, obj, schema);return obj;}@SuppressWarnings("unchecked")private static <T> Schema<T> getSchema(Class<T> clazz) {Schema<T> schema = (Schema<T>) schemaCache.get(clazz);if (Objects.isNull(schema)) {//这个schema通过RuntimeSchema进行懒创建并缓存//所以可以一直调用RuntimeSchema.getSchema(),这个方法是线程安全的schema = RuntimeSchema.getSchema(clazz);if (Objects.nonNull(schema)) {schemaCache.put(clazz, schema);}}return schema;}
}

这里其实就是一个工具类,可以直接调用。下面我将对里面的方法一一讲解
(1)LinkedBUffer字段
社情一个内存空间用户缓存,LinkedBuffer.DEFAULT_BUFFER_SIZE 默认申请了512个字节,我们也可以使用MIN_BUFFER_SIZE ,256个字节。
(2)schemaCache字段
表示缓存的Schema。在这里代表了序列化对象的结构。
(3)serialize方法
序列化方法,西安获得需要序列化的类,然后为它分配一个缓存空间,然后获得此类的Schema.最后一行的代码ProtostuffIOUtil.toByteArray进行序列化。

public static <T> byte[] serialize(T obj) {Class<T> clazz = (Class<T>) obj.getClass();Schema<T> schema = getSchema(clazz);byte[] data;try {data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);} finally {buffer.clear();}return data;}

(4)deserialize
表示反序列化,根据序列化对象获取其组织结构Schema。然后根据byte直接mergeFrom成对象

 public static <T> T deserialize(byte[] data, Class<T> clazz) {Schema<T> schema = getSchema(clazz);T obj = schema.newMessage();ProtostuffIOUtil.mergeFrom(data, obj, schema);return obj;}

(5)getSchema
获取序列化对象的组织结构

private static <T> Schema<T> getSchema(Class<T> clazz) {Schema<T> schema = (Schema<T>) schemaCache.get(clazz);if (Objects.isNull(schema)) {//这个schema通过RuntimeSchema进行懒创建并缓存//所以可以一直调用RuntimeSchema.getSchema(),这个方法是线程安全的schema = RuntimeSchema.getSchema(clazz);if (Objects.nonNull(schema)) {schemaCache.put(clazz, schema);}}return schema;}
}

3、protoStuff实现序列化的原理
在上面的序列化方法中,我们可以看到其实最核心的就是

data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);

我们进到这个方法里

  public static <T> byte[] toByteArray(T message, io.protostuff.Schema<T> schema, LinkedBuffer buffer) {if (buffer.start != buffer.offset) {throw new IllegalArgumentException("Buffer previously used and had not been reset.");} else {ProtostuffOutput output = new ProtostuffOutput(buffer);try {schema.writeTo(output, message);} catch (IOException var5) {throw new RuntimeException("Serializing to a byte array threw an IOException (should never happen).", var5);}return output.toByteArray();}
}

可以看到

schema.writeTo(output, message);

再追进去

public interface Schema<T> {
String getFieldName(int var1);int getFieldNumber(String var1);boolean isInitialized(T var1);T newMessage();String messageName();String messageFullName();Class<? super T> typeClass();void mergeFrom(Input var1, T var2) throws IOException;void writeTo(Output var1, T var2) throws IOException;

}

再追进去我们就会看到它其实就是把序列化对象信息保存成CharSequence ,然后进行序列化
同理追到反序列化。
putObject(message,offset,input,readString());

  public static <T> void mergeFrom(byte[] data, T message, io.protostuff.Schema<T> schema) {IOUtil.mergeFrom(data, 0, data.length, message, schema, true);}

其实就是把序列化对象信息保存成CharSequence,然后序列化。
对于反序列化呢?核心ProtostuffIOUtil.mergeFrom(data, obj, schema);我们也追进去看看

static <T> void mergeFrom(byte[] data, int offset, int length, T message, Schema<T> schema, boolean decodeNestedMessageAsGroup) {try {ByteArrayInput input = new ByteArrayInput(data, offset, length, decodeNestedMessageAsGroup);schema.mergeFrom(input, message);input.checkLastTagWas(0);} catch (ArrayIndexOutOfBoundsException var7) {throw new RuntimeException("Truncated.", ProtobufException.truncatedMessage(var7));} catch (IOException var8) {throw new RuntimeException("Reading from a byte array threw an IOException (should never happen).", var8);}}
 void mergeFrom(Input var1, T var2) throws IOException;

其实以上的跟程序的做法还是要自己再跟一变进一步了解才更深刻,protostuff还是主要以应用为主的。

Java序列化机制——protoStuff相关推荐

  1. java序列化机制之protoStuff

    之前曾经写了两篇java的序列的机制,一种是默认的java序列化机制,这种方式效率太低.另外一种是谷歌的protobuf,但是这种我们还要写proto文件,并且我们还要使用工具来编译生成java文件, ...

  2. 一篇文章搞定java序列化机制

    序列化与反序列化 序列化:将对象的状态信息转换为可以存储或传输的数据形式(比如二进制)的过程. 反序列化:与序列化相对,把序列化转换成的可以存储或传输的数据形式转化为对象的状态信息的过程. java序 ...

  3. Java序列化机制和原理

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一 ...

  4. Java序列化机制原理,java面试题,java基础笔试题,BAT

    写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. Ja ...

  5. java序列化机制Serialize接口使用

    一.理解 Serializable接口是启用其序列化功能的接口.实现java.io.Serializable 接口的类是可序列化的.没有实现此接口的类将不能使它们的任意状态被序列化或逆序列化. 序列化 ...

  6. java transient关键字_嗯?你真的会用 Java 序列化机制?

    码农每日一题长按关注,工作日每天分享一个技术知识点. 一.序列化.反序列化概念及其使用场景 1.序列化.反序列化的概念 简单的讲,序列化就是将java对象转化成二进制保存到磁盘中去,反序列化就是从磁盘 ...

  7. java序列化工具 protoStuff的使用

    1.前言 在互联网快速发展的今天,互联网架构也在不断的升级.而数据的传输和存贮是互联网系统中不可或缺的一部分.举个简单的例子,目前微服务已经很普及了,就拿dubbo来说,不管用jdk自带的序列化,还是 ...

  8. Java序列化的机制和原理

    有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍. Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述 ...

  9. java序列化算法透析_Java序列化机制与原理的深入分析

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一 ...

最新文章

  1. Openfire XMPP Smack RTC IM 即时通讯 聊天 MD
  2. 1.uniq去重命令讲解
  3. 【Tiny4412】设置Uboot提示符和关闭MMU
  4. SAP UI5 应用开发教程之二十四 - 如何使用 OData 数据模型
  5. 您没有足够的全新为该计算机所有用户安装,我用的是admin管理员身份可安装软件弹出你没有足够的权限为该计算机所有用户完成此安装.请以管理员的身份登...
  6. this指针 java_彻底理解Java中this指针
  7. opencv-api warpAffine
  8. redis怎么修改_面试官问我Redis事务,还问我有哪些实现方式
  9. 2019.03.30 图解HTTP
  10. ssm校园在线点餐系统源码(含数据库)
  11. 围棋AI kataGo下载
  12. 软件开发的需求文档如何去写
  13. 计算机图形学与地理信息科学,南京师范大学
  14. 眼疲劳症如何自我检测
  15. Armstrong 一个n位数等于各个位数n次方之和
  16. 利用文本信息引导视觉的模型CLIP
  17. 2019年大厂面试题合集:Java架构师技术栈为什么竞争越来越激烈?程序员必看!
  18. TKinter Listbox
  19. 我的世界服务器领地怎么无限大,《我的世界中国版》地图无限大?边界基础知识介绍...
  20. ICMAX八大方法教你快速分清什么是SD卡与TF卡

热门文章

  1. STM32最小系统搭建(原理图)
  2. 项目笔记30(尚品汇)
  3. 一母同源,荣耀和华为的区别在哪里?
  4. 微信公众号文章复制到服务器后台,微信个人公众号开发-打通后台服务器任督二脉...
  5. 第三十届ACM国际大学生程序设计竞赛全程采访 - 上海交通大学 - 领奖台上
  6. jquery实现酷炫的抽奖器效果
  7. 使用MBG生成MyBatis代码(Intellij版本)
  8. JSP住宅小区物业管理系统(源代码+开题报告+论文+答辩PPT
  9. 安卓玩机搞机----移植第三方rom修复 第三方GSI系统修复bug综合解析【一】
  10. 怎样用matlab实现图像的缩放,matlab实现图像缩放