perf[protocol]: 优化协议注释生成方式

This commit is contained in:
meiwei
2022-07-28 14:18:57 +08:00
parent 1017ae39ab
commit 868d17ba0a
4 changed files with 63 additions and 103 deletions
@@ -61,9 +61,9 @@ public class ConfigManager implements IConfigManager {
public void initRegistry() {
// 通过protocol,写入provider的module的id和version
var providerConfig = localConfig.getProvider();
// 服务提供者名字Set列表
var providerSet = new HashSet<String>();
if (Objects.nonNull(providerConfig) && CollectionUtils.isNotEmpty(providerConfig.getProviders())) {
// 服务提供者名字Set列表
var providerSet = new HashSet<String>();
// 检查并且替换配置文件中的ProtocolModule
for (var providerModule : providerConfig.getProviders()) {
var provider = providerModule.getProvider();
@@ -93,8 +93,6 @@ public class ConfigManager implements IConfigManager {
AssertionUtils.isTrue(protocolModuleSet.add(protocolModuleName), "服务消费者[name:{}]重复消费了协议模块", protocolModuleName);
var consumerName = StringUtils.joinWith(StringUtils.HYPHEN, protocolModuleName, consumer);
AssertionUtils.isTrue(consumerSet.add(consumerName), "服务消费者[name:{}]重复消费了协议模块[consumer:{}]", protocolModuleName, consumer);
//检查是否消费了自己
AssertionUtils.isTrue(!providerSet.contains(consumerName), "服务消费者[name:{}]不允许消费自己[consumer:{}]", protocolModuleName, consumer);
}
}
@@ -15,18 +15,15 @@ package com.zfoo.protocol.generate;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.serializer.anno.Description;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.StringUtils;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* 生成协议的时候,协议的文档注释和字段注释会使用这个类
@@ -77,109 +74,25 @@ public abstract class GenerateProtocolDocument {
AssertionUtils.notNull(protocolDocumentMap, "[{}]已经初始完成,初始化完成过后不能调用initProtocolDocument", GenerateProtocolDocument.class.getSimpleName());
// 文件的注释生成
var proAbsFile = new File(FileUtils.getProAbsPath());
var list = FileUtils.getAllReadableFiles(proAbsFile.getParentFile() == null ? proAbsFile : proAbsFile.getParentFile())
.stream()
.filter(it -> it.getName().endsWith(".java"))
.collect(Collectors.toList());
for (var protocolRegistration : protocolRegistrations) {
var protocolClazz = protocolRegistration.protocolConstructor().getDeclaringClass();
var protocolClazzName = protocolClazz.getName();
var protocolFile = list.stream()
.filter(it -> it.getAbsolutePath().replace(StringUtils.SLASH, StringUtils.PERIOD).replace(StringUtils.BACK_SLASH, StringUtils.PERIOD).endsWith(StringUtils.format("{}.java", protocolClazzName)))
.findFirst();
// 如果搜索不到协议文件则直接返回
if (protocolFile.isEmpty()) {
continue;
}
var docFieldMap = new HashMap<String, String>();
var docTitle = StringUtils.EMPTY;
var protocolStringList = FileUtils.readFileToStringList(protocolFile.get())
.stream()
.dropWhile(it -> !it.startsWith("package")) // 过滤掉package之上的版权信息
.collect(Collectors.toList());
// 搜索包名,报名不匹配则直接返回
var protocolClassTitle = StringUtils.format("public class {}", protocolClazz.getSimpleName());
if (protocolStringList.stream().noneMatch(it -> it.contains(protocolClassTitle))) {
continue;
var description = protocolClazz.getDeclaredAnnotation(Description.class);
if (description != null) {
var docTitleBuilder = new StringBuilder().append("//").append(description.value());
docTitle = docTitleBuilder.toString();
}
protocolStringList = protocolStringList.stream()
.dropWhile(it -> !it.startsWith("package"))
.collect(Collectors.toList());
var docBuilder = new StringBuilder();
var docTitleBuilder = new StringBuilder();
for (var line : protocolStringList) {
var startLineStr = line.trim();
// 排除java的包头
if (startLineStr.startsWith("package") || startLineStr.startsWith("import")) {
var registration = (ProtocolRegistration) protocolRegistration;
for (var field : registration.getFields()) {
var fieldDescrption = field.getDeclaredAnnotation(Description.class);
if (fieldDescrption == null) {
continue;
}
if (startLineStr.startsWith("public class ")) {
if (docTitleBuilder != null) {
docTitle = docTitleBuilder.toString();
docTitle = docTitle.replace("/**", StringUtils.EMPTY);
docTitle = docTitle.replace(" */", StringUtils.EMPTY);
docTitle = docTitle.replace(" *", "//");
docTitle = docTitle.trim();
docBuilder = new StringBuilder();
docTitleBuilder = null;
}
} else {
if (docTitleBuilder != null) {
docTitleBuilder.append(line).append(LS);
}
}
// 保留注释
if (startLineStr.startsWith("*/")) {
continue;
}
if (startLineStr.startsWith("//") || startLineStr.startsWith("*")) {
startLineStr = startLineStr.replaceFirst("//", StringUtils.EMPTY);
startLineStr = startLineStr.replaceFirst("\\*", StringUtils.EMPTY);
docBuilder.append("//").append(startLineStr).append(LS);
continue;
}
if (startLineStr.startsWith("private static ")) {
continue;
}
if (startLineStr.contains(" transient ")) {
continue;
}
if (startLineStr.startsWith("public void set") || startLineStr.startsWith("public bool equals")
|| startLineStr.startsWith("public int hashCode") || startLineStr.startsWith("@Override")) {
continue;
}
if (startLineStr.endsWith("{") || startLineStr.startsWith("return ") || startLineStr.startsWith("}")) {
continue;
}
if (!startLineStr.endsWith(";")) {
continue;
}
if (!(startLineStr.startsWith("private ") || startLineStr.startsWith("public "))) {
continue;
}
var fieldName = StringUtils.substringBeforeLast(StringUtils.substringAfterLast(startLineStr, StringUtils.SPACE), StringUtils.SEMICOLON).trim();
var docBuilder = new StringBuilder().append("//").append(fieldDescrption.value());
var fieldName = field.getName();
docFieldMap.put(fieldName, docBuilder.toString());
docBuilder = new StringBuilder();
}
protocolDocumentMap.put(protocolRegistration.protocolId(), new Pair<>(docTitle, docFieldMap));
@@ -0,0 +1,17 @@
package com.zfoo.protocol.serializer.anno;
import java.lang.annotation.*;
/**
* @author meiw
* @version 3.0
*
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Description {
String value() default "";
}
@@ -445,6 +445,38 @@ public abstract class FileUtils {
return list;
}
/**
* 写入一个content
*
* @param file 文件的绝对路径
* @param content 写入的内容
* @param append 是否追加
*/
public static void writeStringToFile(File file, String content, boolean append) {
// 字节流
FileOutputStream fileOutputStream = null;
// 转换流,设置编码集和解码集 .处理乱码问题,是字节到字符的桥梁
OutputStreamWriter outputStreamWriter = null;
//处理流中的缓冲流,提高效率
BufferedWriter bufferedWriter = null;
// 如果不用缓冲流的话,程序是读一个数据,写一个数据,这样在数据量大的程序中非常影响效率。
// 缓冲流作用是把数据先写入缓冲区,等缓冲区满了,再把数据写到文件里。这样效率就大大提高了
try {
// 以追加的方式打开文件
fileOutputStream = openOutputStream(file, append);
outputStreamWriter = new OutputStreamWriter(fileOutputStream, StringUtils.DEFAULT_CHARSET_NAME);
bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(content);// 写数据
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
// Java的垃圾回收机制不会回收任何的物理资源,只会回收堆内存中对象所占用的内存
// finally总会被执行,即使try块中和catch块中有return,也会被执行。
// 用来显示回收数据库连接,网络连接,磁盘文件
IOUtils.closeIO(bufferedWriter, outputStreamWriter, fileOutputStream);
}
}
/**
* 以追加的方式写入一个content