protobuf基础教程

前端protobuf入门

此文只讲述web前端与后端使用protobuf进行数据交互的基础与入门教学,更加详细的内容请查看google protobuf官方文档以及protobuf项目github地址

准备工作

1.下载protobuf编译器,下载地址, 我的编程环境的Windows平台,所以这里找到并下载protoc-3.5.1-win32.zip,解压出来放到一个你希望放的地方,我这里放在D盘的根目录

2.配置环境变量,配置环境变量只是为了方便命令行编译,所以不一定要配置,环境变量配置到bin目录就好了

3.新建一个测试用的.proto文件

// person.proto  文件
// package 请与需要使用语言的package目录一致

syntax = "proto3";
package com.etertops.protos;

message PersonMessage{
    string id = 1;
    string name = 2;
    string sex = 3;
    string address = 4;
    int32 age = 5;
    string phone = 6;
}

4.编译文件: protoc --java_out=输出目录 需要编译的文件
比如我在文件目录使用protoc --java_out=./ person.proto 编译person.proto编译到当前目录,其他编译请查看官方文档


文件编译

搭建后台服务器

我这里使用的是Spring boot,服务器语言使用的是java,所以上面编译的也是java,关于服务器怎么搭建,这里不做讲述,大家自己搜索。

1.把编译好的Person类拷贝到项目对应的目录下,

2.新增一个控制器用于前端访问,为了方便传输对数据进行了base64编码

// 请先引入依赖
// 依赖仓库地址
https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java
// maven引入
<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.5.1</version>
</dependency>

// 控制器内容
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("proto")
public class ProtobufController {

    @RequestMapping("/get")
    public byte[] send(){
        Person.PersonMessage.Builder personBuilder = Person.PersonMessage.newBuilder();
        personBuilder.setId("test001");
        personBuilder.setName("user test");
        personBuilder.setSex("male");
        personBuilder.setAddress("湖南省长沙市岳麓区银盆岭岳麓大道绿地中央广场");
        personBuilder.setAge(18);
        personBuilder.setPhone("18816881688");
        Person.PersonMessage person = personBuilder.build();
        return Base64.getEncoder().encode(person.toByteArray());
    }
}

前端web页面接收protobuf数据, 使用protobuf.js

// axios.js 用于发起请求
// protobuf.js用于处理protobuf数据,
// github地址: https://github.com/dcodeIO/protobuf.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Protocol Buffer</title>
    <script src="axios.js"></script>
    <script src="protobuf.js"></script>
</head>
<body>
<h1 style="width: 100%; text-align: center">Protocol Buffer Data Test!</h1>
</body>
<script>
    axios.get("../proto/get").then(function (value){
        protobuf.load('../protos/person.proto').then(function (root) {
            var personMessage = root.lookupType('com.etertops.protos.PersonMessage');
            var buffer = new Uint8Array(protobuf.util.base64.length(value.data))
            protobuf.util.base64.decode(value.data, buffer, 0)
            var person = personMessage.decode(buffer);
            console.log(person)
        });
    })
</script>
</html>

前端web页面发送protobuf数据到后端

为了数据稳定,需要先把uint8array转成base64编码的字符串

    function uploadData() {
        protobuf.load('../protos/person.proto').then(function (root) {
            var personMessage = root.lookupType('com.etertops.protos.PersonMessage');
            var payload = {
                id: 'test id from html',
                name: 'protobuf.js',
                sex: '男',
                address: '中华人民共和国',
                age: '16',
                phone: 'made in china'
            };
            var message = personMessage.create(payload);
            var buffer = personMessage.encode(message).finish();
            var b64 = protobuf.util.base64.encode(buffer, 0, buffer.length)
            var fd = new FormData();
            fd.append('proto', b64);
            axios.post('../proto/post', fd).then(function (value) {
                console.log(value)
            })
        });
    }

为什么要转成base64的字符串,我这边是为了方便数据传输,
我直接上传Uint8Array字符数字,在后台解码时,不是获取不到数据就是各种错误。
欢迎各位告诉我java怎么处理接收和处理Uint8Array数据

如果您有更好的方法,还请赐教!

后端接收代码

@RequestMapping(value = "/post", method = RequestMethod.POST)
public void post(String proto){
    try {
        Person.PersonMessage pm = Person.PersonMessage
            .parseFrom(Base64.getDecoder().decode(proto));
        System.out.println("id: " + pm.getId());
        System.out.println("name: " + pm.getName());
        System.out.println("sex: " + pm.getSex());
        System.out.println("address: " + pm.getAddress());
        System.out.println("age: " + pm.getAge());
        System.out.println("phone: " + pm.getPhone());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Java 后台接收protobuf数据

@RequestMapping(value = "/post", method = RequestMethod.POST)
public void post(String proto){
    try {
        Person.PersonMessage pm = Person.PersonMessage
            .parseFrom(Base64.getDecoder().decode(proto));
        System.out.println("id: " + pm.getId());
        System.out.println("name: " + pm.getName());
        System.out.println("sex: " + pm.getSex());
        System.out.println("address: " + pm.getAddress());
        System.out.println("age: " + pm.getAge());
        System.out.println("phone: " + pm.getPhone());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

//打印信息
id: test id from html
name: protobuf.js
sex: 男
address: 中华人民共和国
age: 16
phone: made in china

前端接收protobuf收据,使用google-protobuf,并给后端传递数据

需要node环境

为了方便测试,我在这里使用vue-cli快速搭建一个vue应用,使用其他的node开发环境也是可以的,在此只是方便测试!

关于怎么使用vue-cli的使用,这里不讲,还请自己搜索!

安装依赖 npm install google-protobuf axios --save

由于只是测试,我们直接在APP.vue中写测试代码

通过protoc编译js文件

比如我在文件目录使用protoc --js_out=import_style=commonjs,binary:. person.proto 编译person.proto编译到当前目录,生成person_pb.js文件

直接把编译好的js文件放到vue测试项目的src目录下,由于eslint的原因,文件可以会报错,在文件头部加 /* eslint-disable */ 忽略错误

前端App.vue代码

<template>
  <div id="app">
    <h1 style="width: 100%; text-align: center">Protocol Buffer Data Test!</h1>
    <button style="outline: none; background: yellowgreen; color: wheat" @click="uploadData()">上传数据</button>
  </div>
</template>

<script>
import person from './person_pb'
import axios from 'axios'
import goog from 'google-protobuf'
export default {
  name: 'App',
  created () {
    axios.get('http://localhost:8080/proto/get').then(res => {
      let pm = person.PersonMessage.deserializeBinary(res.data)
      let protoBuf = pm.toObject()
      console.log('protoBuf: ', protoBuf)
    })
  },
  methods: {
    uploadData () {
      let pm = new person.PersonMessage()
      pm.setId('id from google protobuf')
      pm.setName('google protobuf')
      pm.setSex('超人')
      pm.setAddress('中华人民共和国湖南省长沙市')
      pm.setAge(17)
      pm.setPhone('made in changsha')
      let bytes = pm.serializeBinary()
      let b64 = goog.Message.bytesAsB64(bytes)
      let fd = new FormData()
      fd.append('proto', b64)
      axios.post('http://localhost:8080/proto/post', fd).then(function (value) {
        console.log(value)
      })
    }
  }
}
</script>
<style>
</style>

项目源码, 不包含google-protobuf测试源码
https://github.com/rilaohn/protobufabc
google-protobuf测试的源码全部在上面的App.vue代码里,其他的全是vue-cli脚手架的内容,所以并没有上传到github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 参考:http://www.jianshu.com/p/8c6c009bc500 http://blog.csdn...
    F麦子阅读 2,639评论 2 1
  • Protobuf是什么? 官网解释 Protobuf 是Google为序列化数据结构提供的语言无关,平台无关,可扩...
    邝健强阅读 2,528评论 0 4
  • java远程调优可采用两种方式进行连接,jmx与jstatd,此文演示如何配置jmx进行连接调优。 配置指南 De...
    大猪大猪阅读 721评论 0 6
  • 从合肥回来后,开始着手准备身边的土特产品之类的东西。 吃过午饭,卖鸽子老乡开车带我上山里,参观一个养鸡大户。 由于...
    旦旦日记阅读 389评论 0 0
  • 睁眼看世界 不知从何时起,我已经马不停蹄的开始奔跑。 忙着参与活动,忙着参与社团学生会,忙着看书考试。 毕业之后更...
    玉成阅读 421评论 0 1