Protobuf
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.19.1</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>3.19.1</version> </dependency>
参考
https://www.cnblogs.com/ranandrun/p/protobuf.html
protocol编译工具下载:https://github.com/protocolbuffers/protobuf/releases
idea插件安装
proto文件编写
syntax = "proto2"; //生成的类会放在protoc.exe同目录下的tutorial //如果.proto文件中写了java_package,就以java_package为准。 package com; //生成的类会放在protoc.exe同目录下的com.proto.tutorial下 //option java_package = "com"; //最终成的类名 option java_outer_classname = "MyTest"; //要生成的类Person message Data { required string name = 1; optional string email = 2; optional int32 age = 3; }
syntax = "proto2"; //生成的类会放在protoc.exe同目录下的tutorial //如果.proto文件中写了java_package,就以java_package为准。 package com; //生成的类会放在protoc.exe同目录下的com.proto.tutorial下 //option java_package = "com"; //最终成的类名 option java_outer_classname = "PersonTest"; //要生成的类Person message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; }
//使用 proto3 语法 ,未指定则使用proto2 syntax = "proto3"; // proto 文件包名 package com; //生成 proto 文件所在包路径,一般来说是和文件包名一致就可以 //option java_package = "com.wxw.notes.protobuf.proto"; //生成 proto 的文件名 option java_outer_classname="UserProto"; //创建一个 User 对象 message User{ //自身属性 int32 id = 1; string code = 2; string name = 3; // 对象 NickName nickName = 4; //list 引用类型 repeated string strList = 5; // 定义简单的 Map string map<string, string> map = 6; // 定义复杂的 Map 对象 map<string, MapVauleObject> mapObject = 7; } // 定义一个新的Name对象 message NickName { string nickName = 1; } // 定义 Map 的 value 对象 message MapVauleObject { string code = 1; string name = 2; }
编译生成
测试
package com; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.TextFormat; import java.util.Arrays; /** * https://blog.csdn.net/wxw1997a/article/details/116758401 * * @author: zzzzz * @date: 2022/2/21 */ public class Test { public static void main(String[] args) { //convertProto(1); //convertProto2(1); convertProto3(3); } public static void convertProto(int value) { //1.通过build创建消息构造器 MyTest.Data.Builder bulder = MyTest.Data.newBuilder(); //Data.Builder dataBuilder = Data.newBuilder(); //2.设置字段值 bulder.setName("zzzzz"); bulder.setEmail("xx@126.com"); bulder.setAge(100); //dataBuilder.setInt32(value); //3.通过消息构造器构造消息对象 // Data data = dataBuilder.build(); //4.序列化 byte[] bytes = bulder.build().toByteArray(); System.out.println(value + "序列化后的数据:" + Arrays.toString(bytes) + ",字节个数:" + bytes.length); //5.反序列化 try { MyTest.Data parseFrom = MyTest.Data.parseFrom(bytes); System.out.println("还原后的数据=" + parseFrom.toString()); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } public static void convertProto2(int value) { //1.通过build创建消息构造器 PersonTest.Person.Builder bulder = PersonTest.Person.newBuilder(); //Data.Builder dataBuilder = Data.newBuilder(); //2.设置字段值 bulder.setName("zzzz11"); bulder.setEmail("x11x@126.com"); bulder.setId(100000); PersonTest.Person.PhoneNumber.Builder pb = PersonTest.Person.PhoneNumber.newBuilder(); pb.setNumber("100245450"); pb.setType(PersonTest.Person.PhoneType.MOBILE); bulder.addPhone(pb); bulder.addPhone(pb); bulder.addPhone(pb); //dataBuilder.setInt32(value); //3.通过消息构造器构造消息对象 // Data data = dataBuilder.build(); //4.序列化 byte[] bytes = bulder.build().toByteArray(); System.out.println(value + "序列化后的数据:" + Arrays.toString(bytes) + ",字节个数:" + bytes.length); //5.反序列化 try { MyTest.Data parseFrom = MyTest.Data.parseFrom(bytes); System.out.println("还原后的数据=" + System.lineSeparator() + parseFrom.toString()); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } public static void convertProto3(int value) { //初始化数据 UserProto.User.Builder user = UserProto.User.newBuilder(); user.setId(1) .setCode("001") .setName("张三") .build(); //内部对象 UserProto.NickName.Builder nickName = UserProto.NickName.newBuilder(); user.setNickName(nickName.setNickName("昵称").build()); //简单 list user.addStrList("01"); user.addStrList("02"); //简单 map user.putMap("key1", "value1"); user.putMap("key2", "value2"); //object map UserProto.MapVauleObject.Builder objectMap1 = UserProto.MapVauleObject.newBuilder(); user.putMapObject("objectMap1", objectMap1.setCode("code1").setName("name1").build()); UserProto.MapVauleObject.Builder objectMap2 = UserProto.MapVauleObject.newBuilder(); user.putMapObject("objectMap2", objectMap2.setCode("code2").setName("name2").build()); //序列化 UserProto.User build = user.build(); //转换成字节数组 byte[] s = build.toByteArray(); System.out.println("protobuf数据bytes[]:" + Arrays.toString(s)); System.out.println("protobuf序列化大小: " + s.length); UserProto.User user1 = null; String jsonObject = null; try { //反序列化 user1 = UserProto.User.parseFrom(s); System.out.println("反序列化:\n" + user1.toString()); System.out.println("中文反序列化:\n" + printToUnicodeString(user1)); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } // System.out.println("***********************************************"); // //中文反序列化时会转成八进制,可采用 TextFormat.printToUnicodeString 进行转换 // System.out.println("直接反序列化:\n" + printToUnicodeString(user1)); } public static String printToUnicodeString(MessageOrBuilder message) { return TextFormat.printer().escapingNonAscii(false).printToString(message); } }