Google Protocol Buffer应用于Java和JS_深圳市络灵软件系统有限公司

Google Protocol Buffer应用于Java和JS

Websocket中通信打算用Google Protocol Buffer来做。步骤如下:

1.安装Google Protocol Buffer

github下载最新的版本。我用的是windows64位,所以选择protoc-3.7.0-rc-2-win64.zip进行下载。

解压到指定目录后,配置环境变量Path,例:D:\protoc-3.7.0-rc-2-win64\bin;

2.编写.proto文件

proto文件用于定义通信的数据格式。

在java工程src目录下的com.im.common.packets包中创建chat.proto文件,内容如下:

syntax = "proto3";
package com.im.common.packets;

option java_package = "com.im.common.packets";  //设置java对应的package
option java_multiple_files = true; //建议设置为true,这样会每个对象放在一个文件中,否则所有对象都在一个java文件中

/**
 * 聊天类型
 */
enum ChatType {
    CHAT_TYPE_UNKNOW = 0;//未知
    CHAT_TYPE_PUBLIC = 1;//公聊
    CHAT_TYPE_PRIVATE = 2;//私聊
}
/**
 * 聊天请求
 */
message ChatReqBody {
    int64 time = 1;//消息发送时间
    ChatType type = 2; //聊天类型
    string text = 3; //聊天内容
    string group = 4; //目标组id
    int32 toId = 5; //目标用户id,
    string toNick = 6; //目标用户nick
}

/**
 * 聊天响应
 */
message ChatRespBody {
    int64 time = 1;//消息发送时间
    ChatType type = 2; //聊天类型
    string text = 3; //聊天内容
    int32 fromId = 4; //发送聊天消息的用户id
    string fromNick = 5; //发送聊天消息的用户nick
    int32 toId = 6; //目标用户id
    string toNick = 7; //目标用户nick
    string group = 8; //目标组id
}


3.编译文件.proto文件

3.1编译为java代码

使用cmd进入src目录,执行以下命令

protoc  --java_out=./ com/im/common/packets/chat.proto
执行完后,会自动生成相应的java文件。

可以运行以下代码进行测试,代码依赖protobuf-java-3.7.0-rc1.jar、protobuf-java-format-1.4.jar包,请自行下载。

public static void test() {
        try {
            JsonFormat jsonFormat = new JsonFormat();
            ChatRespBody.Builder builder = ChatRespBody.newBuilder();
            builder.setType(ChatType.CHAT_TYPE_PUBLIC);
            builder.setText("Javen 测试");
            builder.setFromId(1);
            builder.setFromNick("Javen");
            builder.setToId(110);
            builder.setToNick("Javen.zhou");
            builder.setGroup("Javen");
            builder.setTime(SystemTimer.currentTimeMillis());
            ChatRespBody chatRespBody = builder.build();
            //从protobuf转json
            String asJson = jsonFormat.printToString(chatRespBody);
            System.out.println("Object to json "+asJson);
            
            byte[] bodybyte = chatRespBody.toByteArray();
            //解码是从byte[]转换为java对象
            ChatRespBody parseChatRespBody = ChatRespBody.parseFrom(bodybyte);
            asJson = jsonFormat.printToString(parseChatRespBody);
            System.out.println("bodybyte to json "+asJson);
            
            //从json转protobuf
            ChatRespBody.Builder _builder = ChatRespBody.newBuilder();
            jsonFormat.merge(new ByteArrayInputStream(asJson.getBytes()), _builder);
            ChatRespBody _chatRespBody = _builder.build();
            asJson = jsonFormat.printToString(_chatRespBody);
            System.out.println("json to protobuf "+asJson);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
 }


3.2编译为js代码

cmd进入com.im.common.packets目录,执行以下命令

protoc --js_out=import_style=commonjs,binary:. chat.proto
执行完会生成chat_pb.js文件,如果是在nodejs中,这个文件可以直接使用了,但是如果是在浏览器环境下使用,还需要进行转换。

在chat_pb.js文件的同级目录下安装引用库,执行nmp命令需要先安装nodejs。

npm install -g require
npm install google-protobuf
npm install -g browserify
创建exports.js文件,文件内容如下:

var chatProto = require('./chat_pb');  
module.exports = {  
DataProto: chatProto  
}

browserify对文件进行编译打包,执行以下命令:

browserify exports.js > chat.js
执行完后生成chat.js,chat.js可以直接在网页中使用了。测试代码如下:

<script src="./chat.js"></script>
<script type="text/javascript">
    var chatReqBody = new proto.com.im.common.packets.ChatReqBody();
    chatReqBody.setTime(new Date().getTime());
    chatReqBody.setText("测试");
    chatReqBody.setType(1);
    chatReqBody.setGroup("Javen");
    chatReqBody.setToid(666);
    chatReqBody.setTonick("Javen205");

    var bytes = chatReqBody.serializeBinary();  
    console.log("序列化为字节:"+bytes);
    var data = proto.com.im.common.packets.ChatReqBody.deserializeBinary(bytes); 
    console.log("反序列化为对象:"+data);  
    console.log("从对象中获取指定属性:"+data.getTonick());
    console.log("对象转化为JSON:"+JSON.stringify(data));  

</script>