由于本人最近在学习Netty,里面涉及了protobuf编译生成java文件的过程,觉得敲命令行比较麻烦,故写了个.prorto文件自动生成java文件的工具类,遇到了不少坑,与大家分享一下,望多多指正。
转载请注明出处:https://blog.youkuaiyun.com/weixin_40929150/article/details/88775559
首先
先配置protobuf的编译环境,本人是win10。
1、下载protoc-win64.zip,解压。
2、配置环境变量
编写工具类
这里主要运用的是java执行CMD命令的原理,其步骤就是:
1、将.proto文件的路径解析拼成 --proto_path=
2、将要输出的java文件路径解析拼成 --java_out=
3、最后通过Runtime依次执行command
这是一个简单的工具类,并不复杂,配置好路径便可直接运行,一些要注意的地方已在注释说明
package netty.utils;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* .proto文件编译成Java文件
* @author:LiChong
* @date:2019/3/23
*/
public class ProtoToJavaUtils {
/**
* 当前项目路径
*/
private static String url = System.getProperty("user.dir");
private static final String PROJECT_NAME = "mahjongtest";
private static String proto_path = "\\src\\main\\resources\\proto";
/**
* 这里一般不需要带包名,因为.proto文件一般为指定包名并自动生成对应的包
*/
private static String java_path = "\\src\\main\\java\\";
/**
* 如果只是想要编译部分(指定)proto文件
* 子包下必须带路径,eg:\\user\\user.proto or \\user.proto
*/
private static final List<String> PROTO_FILES = new ArrayList<>();
/**
* false: 编译部分(指定)proto文件,配合PROTO_FILES
* true: 编译 PROTO_PATH 路径下的所有.proto文件
*/
private static boolean isFiles = true;
private static Runtime runtime = Runtime.getRuntime();
public static void main(String[] args) {
// 指定.proto文件可用
// PROTO_FILES.add("\\user\\user.proto");
// PROTO_FILES.add("\\Test.proto");
// isFiles = false;
// 编译
transform();
}
private static void transform() {
/*
* 这里要注意:
* 如果使用是idea里,有可能当前只是模块(module)而不是项目,获取到url可能只是项目路径
*/
if (!url.endsWith(PROJECT_NAME)) {
url = url + "\\" + PROJECT_NAME;
}
proto_path = url + proto_path;
java_path = url + java_path;
System.out.println("JAVA_PATH:" + java_path);
System.out.println("PROTO_PATH:" + proto_path);
System.out.println("============================File out put===================================");
String command = "";
try {
// 路径下全部
if (isFiles) {
File protoFile = new File(proto_path);
if (protoFile.exists()) {
File[] files = protoFile.listFiles();
for (File file : files) {
command = getCommand(file.getName());
if (!command.isEmpty()) {
outPutJava(command);
}
}
}
} else {
// 指定.proto文件
if (PROTO_FILES.size() > 0) {
for (String protoFile : PROTO_FILES) {
File file = new File(proto_path + protoFile);
if (!file.exists()) {
System.err.println("files is not exist : " + proto_path);
continue;
}
command = getCommand(file.getName());
if (!command.isEmpty()) {
outPutJava(command);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 输出java文件
*
* @param command
* @throws IOException
*/
private static void outPutJava(String command) throws IOException {
System.out.println(">>>:" + command);
// 执行
Process process = runtime.exec(command);
// 打印结果
InputStreamReader isr = new InputStreamReader(process.getErrorStream());
BufferedReader br = new BufferedReader(isr);
boolean isSuccess = true;
String line = null;
while ((line = br.readLine()) != null) {
System.err.println("ERROR:" + line);
isSuccess = false;
}
if (isSuccess) {
System.out.println(">>>:success");
}
br.close();
isr.close();
}
/**
* 获取CMD执行命令
*
* @param fileName
* @return
*/
private static String getCommand(String fileName) {
StringBuffer command = new StringBuffer();
command.append("protoc.exe")
.append(" --java_out=").append(java_path)
.append(" --proto_path=").append(proto_path)
.append(" ").append(fileName);
return command.toString();
}
}
示例
1、会打印出JAVA_PATH和PROTO_PATH
2、会打印执行命令
3、运行成功一般会输出success(有可能遇到特殊情况,success并不一定代表成功,主要看java文件有没有出来)
4、执行出错会输出ERROR