美文网首页protobuf
protobuf基础教程

protobuf基础教程

作者: 天乡墨客 | 来源:发表于2018-03-27 15:30 被阅读0次

    前端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

    相关文章

      网友评论

        本文标题:protobuf基础教程

        本文链接:https://www.haomeiwen.com/subject/fxkscftx.html