[Spring Boot]Protobuf解析MQTT消息体

简述

本文主要针对在MQTT场景下,使用Protobuf协议解析MQTT的消息体

Protobuf下载

官方下载

xml 复制代码
https://github.com/protocolbuffers/protobuf/releases

网盘下载

xml 复制代码
链接:https://pan.baidu.com/s/1Uz7CZuOSwa8VCDl-6r2xzw?pwd=anan 
提取码:anan

本文项目代码

java_fir_mqtt-proto
https://gitee.com/dong-puen/fir_public

配置protoc到Windows系统

解压文件,配置环境变量:

c 复制代码
PROTOCBUF_HOME

Path中添加:

c 复制代码
%PROTOCBUF_HOME%\bin

命令行验证

bash 复制代码
protoc

配置protoc到Ubuntu 22.04.4

安装

shell 复制代码
apt-get install libprotobuf-dev protobuf-compiler

验证

shell 复制代码
protoc

Java集成

MQTT依赖

xml 复制代码
        <!--        mqtt连接依赖-->
        <dependency>
            <groupId>com.hivemq</groupId>
            <artifactId>hivemq-mqtt-client</artifactId>
            <version>1.3.3</version>
        </dependency>

编辑proto文件

protobuf 复制代码
syntax = "proto3";


// 是否开启多文件
option java_multiple_files = true;
// 包命
option java_package = "com.fir.proto.protobuf.info";
// Java外部类名
option java_outer_classname = "Info";

message Info {
  // 字符串
  string name = 1;

  // 整数类型
  int32 int32_value = 3;
  int64 int64_value = 4;
  uint32 uint32_value = 5;
  uint64 uint64_value = 6;
  sint32 sint32_value = 7;
  sint64 sint64_value = 8;
  fixed32 fixed32_value = 9;
  fixed64 fixed64_value = 10;
  sfixed32 sfixed32_value = 11;
  sfixed64 sfixed64_value = 12;

  // 布尔类型
  bool bool_value = 13;

  // 浮点类型
  float float_value = 14;
  double double_value = 15;

  // 字节类型
  bytes bytes_value = 16;

  // 枚举类型
  enum EnumType {
    DEFAULT = 0;
    TYPE1 = 1;
    TYPE2 = 2;
}
  EnumType enum_value = 17;

  // 映射类型
  map<string, int32> map_value = 18;

  // 内嵌消息类型
  message NestedMessage {
    string nested_field = 1;
}
  NestedMessage nested_message = 19;

  // 重复字段
  repeated string repeated_strings = 20;
}

命令行生成Java文件

protobuf 复制代码
protoc --java_out=C:\proto test.proto

(ps:虽然有地方推荐使用idea生成,但是实测有时候会卡住,反而命令行生成速度更快,这里推荐使用命令行。)

复制生成的3个文件

发送数据与解析数据

发送数据

初始化数据

java 复制代码
    @GetMapping("/send")
    public Object pageData() {
        // 构建MesInfo对象
        MesInfo mesInfo = MesInfo.newBuilder()
                .setName("测试数据")
                .build();

        mqttClient.send(mqttClient.TEST_MSG, mesInfo.toByteArray());
        return true;
    }

也可以初始化所有数据对象

java 复制代码
    @GetMapping("/send")
    public Object pageData() {

        // 初始化MesInfo对象
        MesInfo.Builder mesInfoBuilder = MesInfo.newBuilder();

        // 设置字符串字段
        mesInfoBuilder.setName("测试数据");

        // 设置整数类型字段
        mesInfoBuilder.setInt32Value(32);
        mesInfoBuilder.setInt64Value(64L);
        mesInfoBuilder.setUint32Value(32);
        mesInfoBuilder.setUint64Value(64L);
        mesInfoBuilder.setSint32Value(32);
        mesInfoBuilder.setSint64Value(64L);
        mesInfoBuilder.setFixed32Value(32);
        mesInfoBuilder.setFixed64Value(64L);
        mesInfoBuilder.setSfixed32Value(32);
        mesInfoBuilder.setSfixed64Value(64L);

        // 设置布尔类型字段
        mesInfoBuilder.setBoolValue(true);

        // 设置浮点类型字段
        mesInfoBuilder.setFloatValue(3.14f);
        mesInfoBuilder.setDoubleValue(3.141592653589793);

        // 设置字节类型字段
        mesInfoBuilder.setBytesValue(ByteString.copyFromUtf8("字节字符串"));

        // 设置枚举类型字段
        mesInfoBuilder.setEnumValue(MesInfo.EnumType.TYPE1);

        // 设置映射类型字段
        mesInfoBuilder.putMapValue("key1", 100);
        mesInfoBuilder.putMapValue("key2", 200);

        // 设置内嵌消息类型字段
        MesInfo.NestedMessage.Builder nestedMessageBuilder = MesInfo.NestedMessage.newBuilder();
        nestedMessageBuilder.setNestedField("内嵌字段值");
        mesInfoBuilder.setNestedMessage(nestedMessageBuilder.build());

        // 设置重复字段
        mesInfoBuilder.addRepeatedStrings("字符串1");
        mesInfoBuilder.addRepeatedStrings("字符串2");

        // 构建MesInfo对象
        MesInfo mesInfo = mesInfoBuilder.build();

        mqttClient.send(mqttClient.TEST_MSG, mesInfo.toByteArray());
        return true;
    }

解析数据

java 复制代码
    @Bean(name = "mqttBackBean")
    public Consumer<Mqtt3Publish> mqttBackBean() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String datetime = sdf.format(new Date());
        log.info("[MQTT]:" + datetime);
        Consumer<Mqtt3Publish> callback = mqtt3Publish -> {
            String topic;
            topic = mqtt3Publish.getTopic().toString();

            byte[] mqttData = mqtt3Publish.getPayloadAsBytes();

            log.info("[MQTT] 主题{} 消息体 {}}", topic, Arrays.toString(mqttData));

            try {
                MesInfo mesInfo =  MesInfo.parseFrom(mqttData);
                System.out.println("mesInfo============================================================");
                System.out.println(mesInfo.toString());
                System.out.println(mesInfo);
                System.out.println("mesInfo============================================================");

                // 打印所有字段
                for (Map.Entry<Descriptors.FieldDescriptor, Object> entry : mesInfo.getAllFields().entrySet()) {
                    Descriptors.FieldDescriptor field = entry.getKey();
                    Object value = entry.getValue();
                    System.out.println(field.getName() + ": " + value);
                }
            } catch (Exception e) {
                e.printStackTrace();
                // pass
            }
        };
        log.info("[MQTT] 处理结束:" + datetime);
        return callback;
    }

效果如下

相关推荐
qq_2975746721 分钟前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端
老毛肚22 分钟前
MyBatis插件原理及Spring集成
java·spring·mybatis
学嵌入式的小杨同学24 分钟前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
lang2015092835 分钟前
JSR-340 :高性能Web开发新标准
java·前端·servlet
Re.不晚1 小时前
Java入门17——异常
java·开发语言
缘空如是1 小时前
基础工具包之JSON 工厂类
java·json·json切换
追逐梦想的张小年1 小时前
JUC编程04
java·idea
好家伙VCC1 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
南极星10052 小时前
蓝桥杯JAVA--启蒙之路(十)class版本 模块
java·开发语言
消失的旧时光-19432 小时前
第十三课:权限系统如何设计?——RBAC 与 Spring Security 架构
java·架构·spring security·rbac