java 序列化 protobuf_java序列化机制之protobuf(快速高效跨语言)

我们之前曾讲过java自带的一种序列化机制,但是这种机制效率太低,有很多缺点。因此也涌现出了很多优秀的系列化框架,比如说protobuf、protostuff、thrift、hession、kryo、avro、fst、msgpack等等。这篇文章我们就看一下第一个序列化框架protobuf,给出一个简单案例,看看其是如何实现的。注:若你对序列化概念和基本使用还有疑惑,可以翻看我之前的文章,或者百度一些基本概念和作用。

一、为什么要使用protobuf?

使用protobuf的原因肯定是为了解决开发中的一些问题,那使用其他的序列化机制会出现什么问题呢?

(1)java默认序列化机制:效率极低,而且还能不能跨语言之间共享数据。

(2)XML常用于与其他项目之间数据传输或者是共享数据,但是编码和解码会造成很大的性能损失。

(3)json格式也是常见的一种,但是在json在解析的时候非常耗时,而且json结构非常占内存。

但是我们protobuf是一种灵活的、高效的、自动化的序列化机制,可以有效的解决上面的问题。现在应该清楚了吧,正是由于目前的机制存在了很多问题,所以才有了这个序列化框架。

二、如何使用protobuf

protobuf这么优秀使用起来也是非常的简单,我们可以给出其主要的三个步骤,然后使用一个基本的案例去实现一下。

(1)定义.proto文件:我们在这个文件中描述我们序列化的信息,类似于bean类。

(2)根据.proto生成对应的类文件,上面这个proto就像是一个模板,现在我们要根据这个模板创建出一个java类。

(3)序列化。

有了这个基本的步骤我们我们就具体去实现一下:

1、下载安装protobuf

第一步:下载解压

我的电脑是windows10,因此这里给出在windows下的使用,linux下面使用我也将在后续文章推出。我们首先下载protobuf(github上搜索protobuf,有各种语言可供选择)。选择protoc-3.9.0-win64.zip。下载完成之后解压到D:/protobuf目录下面就好了。

第二步:配置环境变量

也就是将D:\protobuf\protoc-3.9.0-win64\bin配置到path环境变量里面。

第三步:验证是否安装成功

最后我们可以在cmd中输入protoc --version验证一下,是否成功。

OK,到这里我们就安装好了。

2、编写proto文件

之前我们说过proto 文件非常类似java的bean。在这里我们在bin目录下新建一个Person.proto文件(和proto.exe)。输入下列内容:

syntax="proto3";

option java_package = "com.fdd.protobuf";

option java_outer_classname = "PersonProto";

message Person {

string name = 1;

int32 age = 2;

}

我们解释一些我们都写了什么

(1)第一行有一个proto3,他表示的是protobuf的语法版本,就类似于jdk1.7和jdk1.8的概念。需要在第一行指定。默认使用的是proto2。

(2)java_package:表示的是java包,不指定就使用 package.生成的类会放到该package下。这里表示把生成的类存放在com.fdd.protobuf包下面。

(3)java_outer_classname:我们说过.proto文件,要生成对应的类,这个参数就指定输出什么类名。这里表示生成的类名是PersonProto。

(4)message 是用于数据格式定义.一个 .proto 文件中可以定义多个 message

message 中定义的字段支持 string、byte、bool、map、enum、数字类型和用户自定义的 message

定义字段后面需要指定唯一的标识数字,这些数字用于识别二进制格式 message 中的字段,一旦开始使用这个 message,那么标识数字就不能改变

如果需要定义 List,则在字段前加repeated即可.

如果已经使用过该 message 生成的类后,想要增加字段直接新增即可.当新增字段的类解析老数据时,会将新字段置为默认值.当旧的类解析新数据时会忽视掉新增字段.

比如说这里我们就定义一个复杂的proto文件:

syntax = "proto3";

option java_package = "com.fdd.protobuf";

option java_outer_classname = "Persons";

message Staff {

int32 id = 1;

string name = 2;

int32 age = 3;

// 枚举示例 enum PhoneType {

MOBILE = 0;

TELEPHONE = 1;

}

// 嵌套示例 message PhoneNumber {

string number = 1;

PhoneType type = 2;

}

// list示例 repeated PhoneNumber phone = 4;

message Map {

string key = 1;

int32 value = 2;

}

// map示例 Map map = 5;

}

由于这里只是展示一个基本案例,对于其他的数据类型可以根据自己的需要定义即可。

3、根据proto文件生成class类文件

编译起来很简单,在我们下载好的protobuf下面有一个bin目录,里面有一个proto.exe。我们就使用这个去编译person.proto文件就好。

也就是执行proto.exe --java_out = / Person.proto就会编译成功。

4、使用class类文件

上面意味着我们已经做好了序列化的准备工作,接下来我们就可以直接使用这个类了。

(1)第一步:将生成的PersonProto类引入到我们的IDEA或者是eclipse中。

(2)第二步:在idea或者是eclipse添加protobuf的依赖。

com.google.protobuf

protobuf-java

3.9.0

(3)第三步:使用

首先看一些如何序列化:

//1、 创建BuilderPersonProto.Person.Builder builder = PersonProto.Person.newBuilder();

//2、 设置Person的属性builder.setAge(20);

builder.setName("java的架构师技术栈");

//3、 创建PersonPersonProto.Person person = builder.build();

//4、序列化byte[] data = person.toByteArray();

//5、将data保存在本地或者是传到网络

然后反序列化

try {

//一行代码实现反序列化,data可以是本地数据或者是网络数据 PersonProto.Person person = PersonProto.Person.parseFrom(data);

System.out.println(person.getAge());

System.out.println(person.getName());

} catch (InvalidProtocolBufferException e) {

e.printStackTrace();

}

简单吧,基本上就是我们定义好proto文件,然后使用proto.exe编译成类文件,最后导入这个类和依赖就可以直接使用了。当然这只是一个最简单不过的代码,可以把这篇教程当成一个简单的使用教程。一般情况是是结合SpringBoot来使用的。具体使用会陆续推出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/406120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 四舍五入

如果把float或者double进行强制转换的话,都是进行的截尾操作,例如 float b1 1.3f; float b2 1.7f; System.out.println((int)b1"---"(int)b2); 结果是:1---1 如果要进行四舍五入的话,采用java.lang.Math中的round方法…

使用js将驼峰命名法与-命名的切换

使用js将驼峰命名法与-命名的切换

深入react技术栈(2):JSX语法

JSX的由来 DOM元素 组件元素 JSX基本语法 XML基本语法 元素类型 、我们讲到两种不同的元素:DOM元素和组件元素 在JSX里面有对应 注释 元素属性 Boolean属性 展开属性 自定义属性 javascript属性表达式 属性值使用表达式 用{}表示 HTML转义 文章参考深入react学习技术栈

关于在n-1的数组中找到那个被减去的数及异或与位与

// 有1到N共 n-1个数,问少了哪个数 // 有序数组(如果是无序数组那么将a[i] 移动至 a[a[i]] 这样子就成功排序了) //其实可以采用byte数组的来做,感觉会更快 //当然,这个更多的是用在1-n 共n1个数,问多出来的那个数是多少&#xff…

linux内存映射函数mmap

From: http://hi.baidu.com/cchaha0227/blog/item/7bb7911f4299eb02314e157e.html Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 头文件: <unistd.h…

用css改变input光标的3种方法

用css改变input光标的3种方法

鄙视和膜拜

在汉化的世界 流行两种风气 鄙视和膜拜 常常看GAL论坛都是 膜拜大大, BS 不敢明目张胆。但是字面上白地黑子很明显表示 出BS情绪 我今天谈谈 昨天和血色玲珑交流的心得 首先 汉化不值得膜拜的 F大就喷我了: 搞汉化&#xff0c;其实什么都不算&#xff0c;根本没什么了不起。 好…

java map 允许重复_java中key值可以重复的map:IdentityHashMap

在Java中&#xff0c;有一种key值可以重复的map&#xff0c;就是IdentityHashMap。在IdentityHashMap中&#xff0c;判断两个键值k1和 k2相等的条件是 k1 k2 。在正常的Map 实现(如 HashMap)中&#xff0c;当且仅当满足下列条件时才认为两个键 k1 和 k2 相等&#xff1a;(k1nu…

JS 获取图片的原始尺寸

JS 获取图片的原始尺寸

深入react技术栈(3):React组件

我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注前端小歌谣 终于说出最为关心的react组件了。在react形成之前,组件封装都是在摸索之中 组件的演变 class定义组件的样式 这样可以方便的定义class前缀 一达到定义一系列主题的意义 初始化过程十分简洁 实例化传入几个参数给…

grep的时候Binary file (standard input) matches 怎么解决?

From: http://blog.csdn.net/iori97king/article/details/5917824 操作 grep "xxx" a.log 结果 Binary file a.log matches 原因&#xff1a;grep认为a.log是二进制文件 解决方法&#xff1a; grep -a "xxx" a.log 可以看看grep -a参数的功能 [appadminte…

CGAffineTransform

//移动效果 CGAffineTransform CGAffineTransformMakeTranslation ( CGFloat tx, CGFloat ty );CGAffineTransform CGAffineTransformTranslate ( CGAffineTransform t, CGFloat tx, CGFloat ty );//旋转效果 CGAffineTransform CGAffineTransformMakeRotation …

大城市求职生活建议

这算是被网友提示的一个很新颖的话题。我以前也一直没有思考过&#xff0c;嗯&#xff0c;想想觉得很有讨论的必要&#xff0c;所以写点自己的看法。 还是那句话&#xff0c;一家之言&#xff0c;欢迎拍砖哈。 话题的大意是这样的&#xff0c;一个网友&#xff0c;在开封上大学…

java item方法_Java常用方法

第一章 字符串1 、 获取字符串的长度&#xff1a; length()2 、 判断字符串的前缀或后缀与已知字符串是否相同前缀 startsWith(String s) 、后缀 endsWith(String s)3 、 比较两个字符串&#xff1a; equals(String s)4 、 把字符串转化为相应的数值int 型 Integer.parseInt( 字…

深入react技术栈(4):React数据流

我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注前端小歌谣 state props 子组件props 组件props function prop 与父组件通信 propTypes 文章参考深入react学习技术栈

QNetworkRequest 请求类

QNetworkRequest Class Header: #include <QNetworkRequest>qmake: QT networkSince: Qt 4.4这个QNetworkRequest类保存了一个将被QNetworkAccessManager发送的请求.QNetworkRequest是Network Access API的一部分,是在网络上保存着发送一个请求的必要信息.它…

Oracle 索引的维护

一&#xff0e;查看系统表中的用户索引在Oracle中&#xff0c;SYSTEM表是安装数据库时自动建立的&#xff0c;它包含数据库的全部数据字典&#xff0c;存储过程、包、函数和触发器的定义以及系统回滚段。一般来说&#xff0c;应该尽量避免在SYSTEM表中存储非SYSTEM用户的对象。…

vue中this.$nextTick()的用法

vue中this.$nextTick()的用法

学会用taro封装一个组件

我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注前端小歌谣学习前端知识 前言 大家好 我是歌谣 今天要说得是用taro封装一个组件 核心是学会弹性布局 直接上代码 组件部分 子组件 import Taro, { Component } from "tarojs/taro"; import { Text, View, Image…

Linux C获取文件属性

From: http://www.tianya360.com/html/xitonganzhuang/caozuoxitong/2010/0524/924.html Linux下如何在C下面判断一个文件是不是连接&#xff1f;判断上面生成的软连接文件link,执行后&#xff0c;程序却说是目录&#xff0c;不知道是为什么&#xff1f;源代码如下&#xff1a;…