1. 絮絮叨叨
- 都说懒惰是人类进步的源泉,有时候想想还真就那么回事
- 学习了如何使用protoc命令编译,重度依赖IDEA且已经习惯了maven的我,就在想是否能在IDEA中一键编译.proto文件
2. vscode配置protobuf编辑环境
- 由于自己习惯了使用vscode做文本阅读,因此通过protoc命令编译的.proto文件,最开始都是通过vscode查看
- 使用vscode查看的过程中,发现没有预发高亮,简单的内容修改,也没有语法提示
- 因此,自己首先想为vscode配置protobuf编辑环境
2.1 安装相关插件
- vscode配置protobuf编辑环境,需要安装插件vscode-proto3、Clang-Format
- 参考博客:Mac 技术篇-VS Code插件安装方法,查看vscode已安装插件的方法
- 写好的protobuf代码,可以
右键
→ \rightarrow →Format Document
进行格式化,或者通过快捷键⌥⇧F 进行格式化
2.2 The ‘clang-format’ command is not available问题的解决
-
如果提示
The 'clang-format' command is not available
,具体报错信息如下:The 'clang-format' command is not available. Please check your clang-format.executable user setting and ensure it is installed.
-
自己检查发现又发现Clang-Format已经成功安装,这时需要通过命令进行安装:
brew install clang-format
-
找了很多方法,目前就这个办法亲测ok。感谢博客:Golang 集成 Protobuf 及 vscode 配置
3. IDEA配置protobuf编辑环境
- 插件配置,主要是为了能实现protobuf的语法高亮、代码提示
- idea配置protobuf,好多博客都推荐Protobuf Support
- 自己的idea不知道什么时候,已经安装上了gRPC及其依赖Protocol Buffers,撰写proto文件时会有代码提示和语法高亮
- 就凑合这样使用吧 😂
4. maven + protobuf配置
4.1 配置maven依赖
-
通过maven将proto文件编译成Java源代码,需要添加
protobuf-java
依赖<properties> <protobuf.version>3.19.4</protobuf.version> </properties> <dependencies> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>${protobuf.version}</version> </dependency> </dependencies>
-
进行builder插件设置,<protoSourceRoot>、<outputDirectory>、<clearOutputDirectory>,这三个参数非常有用使用时可以灵活设置
<build> <extensions> <!--这个必须添加,否则plugin下的${os.detected.classifier}可能会报错--> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.1</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.5.1</version> <configuration> <!-- proto文件放置的目录 --> <protoSourceRoot>${basedir}/src/main/proto</protoSourceRoot> <protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact> <!-- 生成文件的目录, 可以让其在源码目录生成 --> <!-- <outputDirectory>${project.basedir}/src/main/java</outputDirectory>--> <!-- 生成文件前是否把目标目录清空,这个最好设置为false,以免误删项目文件 --> <!-- <clearOutputDirectory>false</clearOutputDirectory>--> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
-
是否成功配置maven的protobuf编译功能,点击左上角的
Maven
,查看Plugins中是否存在protobuf插件
-
protobuf-maven-plugin还有很多其他的参数,具体可以参考文档:Maven Protocol Buffers Plugin
4.2 创建.proto文件
-
按照惯例,可以在
src/main/proto
目录下撰写.proto文件 -
首先,需要在
src/main
目录下创建一个proto目录,并将其设置为Sources Root
或者Resources Root
-
不管设置为Sources Root还是Resources Root,亲自验证都可以实现编译
-
这里直接使用protobuf官网的示例代码,稍作修改写入
address_book.proto
文件中// 只修改了java_package option java_package = "com.sunrise.protos";
4.3 编译.proto文件
- 点击左上角Maven
→
\rightarrow
→ Plugins
→
\rightarrow
→ protobuf
→
\rightarrow
→ protobuf:compile,进行proto文件的编译
- 在
target/generated-sources/protobuf/java
目录下,成功生成一些Java文件
- 打开AddressBook类,对应
message AddressBook
发现可能是因为自动生成代码的原因,代码乱得一匹,让人难以阅读 😂
- 此时,自己最想做的是:① 使用import语句精简代码、格式化代码(4个空格的缩进);② 将生成的代码剪切到
src/java/main
目录下
在src/java/main
目录生成代码
-
对于②,实际可以通过配置<outputDirectory>,使生成的代码位于我们习惯的
src/java/main
目录 -
需要注意的是,如果设置<outputDirectory>为
src/java/main
目录,一定要记得设置<clearOutputDirectory>参数,避免代码目录一下被清空了😱<!-- 生成文件的目录, 让其在源码目录生成 --> <outputDirectory>${project.basedir}/src/main/java</outputDirectory> <!-- 生成文件前是否把目标目录清空,这个最好设置为false,以免误删项目文件 --> <clearOutputDirectory>false</clearOutputDirectory>
4.4 如何解决import导入的.proto文件not found问题?
4.4.1 protobuf自带的.proto文件
-
基于官方文档示例代码,现在增加Duration这一数据类型
-
这是protobuf自定义的一种数据类型,在protobuf安装包或maven plugin中,有对应的.proto文件可以直接使用
-
代码修改如下,主要是加入import定义和对应的duration字段
// package之后、option之前,添加import语句 import "google/protobuf/duration.proto"; // message Person中新增字段 optional google.protobuf.Duration duration = 5;
-
此时,通过maven编译.proto没有任何报错,能成功编译
4.4.2 为何2.6.1编译报错?
- 这下子把我搞懵逼了,明明之前引入duration.proto后,通过maven进行编译报错了
- 后来,仔细查看了下:
- duration.proto最早commit的时间为2015年2月9日
- 而protobuf 2.6.1的发布时间为2014年10月21日
- 因此,大胆猜测:2.6.1版本的protobuf-java依赖中,是没有duration.proto,导致编译报错
- duration.proto最早commit的时间为2015年2月9日
4.4.3 <additionalProtoPathElements>参数
-
通过仔细查看Maven Protocol Buffers Plugin官网,找到了一个感觉合适的参数<additionalProtoPathElements>
-
事实证明,感觉没有错 😜
<additionalProtoPathElements> <additionalProtoPathElement>/usr/local/include/</additionalProtoPathElement> </additionalProtoPathElements>
-
虽然最后的编译报错了,但是起码从报错信息来看,plugin找到了duration.proto
正确的配置示例
-
在
src/main
目录下,自定义bar.proto:syntax = "proto2"; package my_protos; message Bar { required string name = 1; required int32 id = 2; optional string comment = 3; }
-
更新之前的address_book.proto,使用自定义的bar.proto,而非google的duration.proto
// 修改import语句 import "bar.proto"; // 修改序号为5的字段 optional my_protos.Bar bar = 5;
-
更新pom.xml,配置<additionalProtoPathElements>参数
<additionalProtoPathElements> <additionalProtoPathElement>${basedir}/src/main/</additionalProtoPathElement> </additionalProtoPathElements>
-
再次进行编译,编译成功 !
5. 其他
- 感谢博客,让我成功通过maven编译proto文件:idea中配合protobuf使用生成Java文件
- 感谢博客,让我找到了不用从
target/generated-sources/protobuf/java
拷贝生成的Java代码的方法:IDEA + Maven + Protobuf 配置和使用 - 感谢博客,让我更全面的了解protobuf-maven-plugin的参数:Maven Protobuf 详细配置