某日工作时需要将类中所有方法详细信息收集到excel中,包括方法的参数注释信息,方法签名注释信息,返回值注释信息,方法上的注解信息,而我需要列举的类方法有80 90个那不是累死人。突然想到曾经写过通过javadoc获取注释信息的功能,而注解信息,通过jdk暴露出来的api 是获取不到,需要另辟蹊路,经过研究我发现sun.javadoc中有注解的信息,只是没有暴露出来,在他的com.sun.tools.javac.tree.JCTree.JCMethodDecl类中,我使用了反射私有属性获取到了该信息。现提供解决方案如下,供有需要的兄弟享用:
1、首先你使用sun.javadoc需要依赖jdk的tools.jar,在gradle中添加依赖
compile files("${System.properties['java.home']}/../lib/tools.jar")
2、代码调用
/**
*
*/
@Test
public void generateRestFullExcel() {
com.sun.tools.javadoc.Main
.execute(new String[] { "-doclet", Doclet.class.getName(), "-docletpath",
Doclet.class.getResource("/").getPath(), "-encoding", "utf-8", "-classpath",
"D:/xxx/bin;",
"D:/xxx/xxx.java" });
JSONArray datas = show();
String[] title = { "方法名称", "方法说明", "入参", "出参", "注解" };
// 创建excel工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
// 创建工作表sheet
HSSFSheet sheet = workbook.createSheet();
// 创建第一行
HSSFRow row = sheet.createRow(0);
HSSFCell cell = null;
// 插入第一行数据的表头
for (int i = 0; i < title.length; i++) {
cell = row.createCell(i);
cell.setCellValue(title[i]);
}
Map map = new HashMap<>();
map.put("方法名称", "engName");
map.put("方法说明", "description");
map.put("入参", "params");
map.put("出参", "returnType");
map.put("注解", "annotation");
for (int j = 0; j < datas.size(); j++) {
JSONObject obj = datas.getJSONObject(j);
HSSFRow nrow = sheet.createRow(j + 1);
for (int i = 0; i < title.length; i++) {
HSSFCell ncell = nrow.createCell(i);
ncell.setCellValue(obj.getString(map.get(title[i])));
}
}
// 创建excel文件
File file = new File("D:/xxx/xxx.xlsx");
try {
file.createNewFile();
// 将excel写入
FileOutputStream stream = FileUtils.openOutputStream(file);
workbook.write(stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/** */
private static RootDoc root;
// 一个简单Doclet,收到 RootDoc对象保存起来供后续使用
// 参见参考资料6
/**
*
* @author 许畅
* @since JDK1.7
* @version 2019年5月24日 许畅 新建
*/
public static class Doclet {
/**
* @param root1 xx
* @return xx
*/
public static boolean start(RootDoc root1) {
JavaDocTest.root = root1;
return true;
}
}
/**
* @return xx
*/
public static JSONArray show() {
ClassDoc[] classes = root.classes();
JSONArray array = new JSONArray();
for (int i = 0; i < classes.length; ++i) {
System.out.println(classes[i]);
System.out.println(classes[i].commentText());
for (MethodDoc method : classes[i].methods()) {
if (!method.isPublic()) {
continue;
}
JSONObject jsonMethod = new JSONObject();
jsonMethod.put("engName", method.name());
jsonMethod.put("description", method.commentText());
jsonMethod.put("process", "用于" + method.commentText());
Field treeField = ReflectionUtils.findField(method.getClass(), "tree");
try {
treeField.setAccessible(true);
JCMethodDecl tree = (JCMethodDecl) treeField.get(method);
jsonMethod.put("annotation", tree.mods.annotations.toString());
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
AnnotationDesc[] annotations = method.annotations();
for (AnnotationDesc annotationDesc : annotations) {
System.out.println(annotationDesc);
}
String returnTypeValue = method.tags("return").length > 0 ? method.tags("return")[0].text() : null;
jsonMethod.put("returnType", returnTypeValue);
System.out.println("方法返回值:" + returnTypeValue);
System.out.println("方法名称:" + method.name());
System.out.println(method.commentText());
ParamTag[] paramTags = method.paramTags();
System.out.println("方法参数:");
JSONArray params = new JSONArray();
StringBuilder sb = new StringBuilder();
for (int j = 0; j < paramTags.length; j++) {
if (j > 0) {
sb.append(",");
}
ParamTag paramTag = paramTags[j];
JSONObject param = new JSONObject();
params.add(param);
param.put("engName", paramTag.parameterName());
sb.append(paramTag.parameterName());
sb.append(":");
param.put("description", paramTag.parameterComment());
sb.append(paramTag.parameterComment());
System.out.println(paramTag.parameterName());
System.out.println(paramTag.parameterComment());
}
jsonMethod.put("params", sb.toString());
jsonMethod.put("parameters", params);
array.add(jsonMethod);
}
}
System.out.println(array);
return array;
}