物联网 Protobuf文本协议入门

0 阅读1分钟

物联网 Protobuf文本协议入门

Protobuf(Protocol Buffers)是Google开发的高效、跨语言的序列化框架,相比JSON/XML等文本协议,Protobuf在性能、空间占用和跨语言支持方面具有显著优势

源码

源码[gitee.com/kcnf-webrtc…]

proto文件定义与语法规范

基础语法

定义用户数据结构的示例文件(src/main/proto/user.proto):

syntax = "proto3";

package com.jysemel.iot.protobuf;

option java_package = "com.jysemel.protobuf.model";
option java_outer_classname = "UserProto";

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
  int32 age = 4;
}
针对上面关键语法说明

语法项

说明

syntax = "proto3"

指定使用Protocol Buffers v3版本

option java_package

定义生成的Java类包路径

option java_outer_classname

定义生成的外层类名(用于嵌套消息)

repeated

定义列表类型字段,对应Java中的List或数组

注意事项
  • 其中User和java_outer_classname 名称不要冲突,否则编译出现下面错误

protoc did not exit cleanly. Review output for more information.

img

添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.jysemel.iot</groupId>
        <artifactId>iot-sample</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>protobuf</artifactId>
    <packaging>pom</packaging>

    <modules>
        <module>protobuf-api-01</module>
        <module>protobuf-api-02</module>
        <module>protobuf-sample01</module>
        <module>protobuf-sample</module>
    </modules>



    <properties>
        <protobuf.version>3.21.12</protobuf.version>
    </properties>

    <dependencies>
        <!-- Protobuf Java 支持 -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>${protobuf.version}</version>
        </dependency>

        <!-- 可选:支持更便捷的 Protobuf 消息转换 -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java-util</artifactId>
            <version>${protobuf.version}</version>
        </dependency>
    </dependencies>

    <build>
        <extensions>
            <!-- OS 检测插件,用于 protobuf 插件 -->
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.7.0</version>
            </extension>
        </extensions>
        <plugins>
            <!-- Spring Boot Maven 插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <!-- Protobuf 编译插件 -->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.21.12:exe:${os.detected.classifier}</protocArtifact>
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>
                    <clearOutputDirectory>false</clearOutputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

执行编译后面代码

img

序列化与反序列化示例

package com.jysemel.iot;

import com.google.protobuf.InvalidProtocolBufferException;
import com.jysemel.protobuf.model.UserProto;

public class ProtoBufDemo {
    public static void main(String[] args) {
        // 1. 构建User对象
        UserProto.User user = UserProto.User.newBuilder()
                .setId(123)
                .setName("Alice")
                .setEmail("alice@example.com")
                .setAge(25)
                .build();

        // 2. 序列化为字节数组
        byte[] data = user.toByteArray();
        System.out.println("Serialized data length: " + data.length);

        // 3. 反序列化
        try {
            UserProto.User parsedUser = UserProto.User.parseFrom(data);
            System.out.println("Parsed User: " + parsedUser);
            System.out.println("Name: " + parsedUser.getName());
            System.out.println("Email: " + parsedUser.getEmail());
            System.out.println("Age: " + parsedUser.getAge());
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
    }
}

关键方法说明

方法

说明

toByteArray()

将消息序列化为字节数组

writeTo(OutputStream)

将消息写入输出流(适用于网络传输)

parseFrom(byte[])

从字节数组反序列化消息

parseDelimitedFrom(InputStream)

从带长度前缀的输入流反序列化消息(适用于流式传输)

Protobuf与JSON互转
package com.jysemel.iot;

import com.google.protobuf.util.JsonFormat;
import com.jysemel.protobuf.model.UserProto;

public class JsonConversionDemo {

    public static void main(String[] args) throws Exception {
        // 1. 构建User对象
        UserProto.User user = UserProto.User.newBuilder()
                .setId(123)
                .setName("Alice")
                .setEmail("alice@example.com")
                .setAge(25)
                .build();

        // Protobuf转JSON
        String json = JsonFormat.printer().print(user);
        System.out.println("JSON: " + json);

        // JSON转Protobuf
        UserProto.User.Builder builder = UserProto.User.newBuilder();
        JsonFormat.parser().merge(json, builder);
        UserProto.User parsedUser = builder.build();
        System.out.println("Parsed from JSON: " + parsedUser);
    }

}