java反射 - 解析注释
使用 swagger 的时候,产生了这样一个想法:代码中本身就有一套注释,为啥还要引入一套注解,这不是在做重复的工作么?
要完成这个工作,需要用到 tools.jar,不需要下载,从 jdk 中复制即可。
优点:
- 解决了代码与 swagger 之间的耦合,正常写代码注释即可,降低了学习成本。
缺点:
- java 文件编译成 class 文件之后,代码中的注释会被清空,所以只能在前期使用。
- 正式部署项目的时候,还要删除 tools.jar 包,不然会被检测出一些系统漏洞。
<!--JavaDoc-->
<dependency>
<groupId>com.sun.javadoc</groupId>
<artifactId>com.sun.javadoc</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/tools.jar</systemPath>
</dependency>
使用方式与 java 反射十分类似,下列代码展示了最基础的使用。
package cn.seaboot.plugin;
import cn.seaboot.admin.bean.core.SysAppInfo;
import cn.seaboot.common.core.CommonUtils;
import com.sun.javadoc.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
/**
* 注释解析依赖于 .class 文件和 .java 文件,因此参数中需要文件存放路径,
* 其余代码与 java 反射非常一致
*
* @author Mr.css
* @date 2020-07-28 14:24
*/
public class JavaApi {
private static RootDoc rootDoc;
/**
* class 文件的地址
*/
private static String classPath = "D:/seaboot/admin/target/classes";
/**
* 工程路径,用于拼接 java 文件的地址
*/
private static String projectPath = System.getProperty("user.dir") + "/";
/**
* java 文件路径
*/
private static String javaPath = "src/main/java/";
/**
* 要实现注释解析,必须存在这个函数,算是约定俗成的写法
* a interface of javadoc
*
* @param rootDoc rootDoc
* @return true
* @see com.sun.tools.javadoc.Main
*/
public static boolean start(RootDoc rootDoc) {
JavaApi.rootDoc = rootDoc;
return true;
}
public static String getClassPath() {
return classPath;
}
public static void setClassPath(String classPath) {
JavaApi.classPath = classPath;
}
public static String getProjectPath() {
return projectPath;
}
public static void setProjectPath(String projectPath) {
JavaApi.projectPath = projectPath;
}
public static String getJavaPath() {
return javaPath;
}
public static void setJavaPath(String javaPath) {
JavaApi.javaPath = javaPath;
}
public static RootDoc getRootDoc(Class clazz) throws FileNotFoundException {
String filePath = projectPath + javaPath + clazz.getPackage().getName().replace(".", "/")
+ "/" + clazz.getSimpleName() + ".java";
File file = new File(filePath);
if (!file.exists()) {
throw new FileNotFoundException("java file not found: " + filePath);
}
com.sun.tools.javadoc.Main.execute(new String[]{"-doclet",
JavaApi.class.getName(),
"-encoding", "utf-8", "-classpath",
classPath,
filePath});
return rootDoc;
}
public static String getSignature(MethodDoc methodDoc) {
Parameter[] parameters = methodDoc.parameters();
if (CommonUtils.isEmpty(parameters)) {
return null;
} else {
StringBuilder sb = new StringBuilder();
sb.append(parameters[0].type());
for (int i = 1; i < parameters.length; i++) {
sb.append(",").append(parameters[i].type());
}
return sb.toString();
}
}
public static String getSimpleSignature(MethodDoc methodDoc) {
Parameter[] parameters = methodDoc.parameters();
if (CommonUtils.isEmpty(parameters)) {
return null;
} else {
StringBuilder sb = new StringBuilder();
sb.append(parameters[0].type().simpleTypeName());
for (int i = 1; i < parameters.length; i++) {
sb.append(",").append(parameters[i].type().simpleTypeName());
}
return sb.toString();
}
}
public static String getParameterText(MethodDoc methodDoc, String name) {
ParamTag[] paramTags = methodDoc.paramTags();
for (ParamTag tag : paramTags) {
if (tag.parameterName().equals(name)) {
return tag.parameterComment();
}
}
return null;
}
public static void getApi(Class clazz) throws FileNotFoundException {
RootDoc rootDoc = getRootDoc(clazz);
for (ClassDoc classDoc : rootDoc.classes()) {
System.out.println(classDoc.commentText());
System.out.println(Arrays.toString(classDoc.methods()));
}
}
public static void main(String[] args) throws FileNotFoundException {
getApi(SysAppInfo.class);
}
}
//异常注解,对应@throws
//methodDoc.throwsTags()
//参考注解,对应@see
//methodDoc.seeTags()
//获取返回值注解,对应于@return
//methodDoc.tags("@return");
//获取全部的 method 参数类型,存在函数重载的场合,函数名与参数类型,才能共同确认唯一 Method
//methodDoc.signature()
//获取返回值类型,与 java 反射同
//methodDoc.returnType()
//获取完整的注释(遇到无法解析的,可以手动解析,包含method注解,param注解,return注解...)
//methodDoc.getRawCommentText()
//获取方法注解
//methodDoc.commentText()
//获取全部注解
//methodDoc.tags();
//获取参数注解
//methodDoc.paramTags()
//ParamTag[] paramTags = methodDoc.paramTags();
//for(ParamTag paramTag: paramTags){
// System.out.println(paramTag.isTypeParameter());
// System.out.println(paramTag.parameterComment());
// System.out.println(paramTag.parameterName());
//}
//暂无详细资料
//methodDoc.typeParamTags();
//获取第一句注解,与methodDoc.commentText()同
//methodDoc.firstSentenceTags()
//暂无详细资料,与methodDoc.commentText()同
//methodDoc.inlineTags();
// Parameter[] parameters = methodDoc.parameters();
// for (Parameter parameter : parameters) {
// System.out.println(parameter.toString());
// AnnotationDesc[] annotations = parameter.annotations();
// for (AnnotationDesc annotationDesc: annotations){
// System.out.println("-----" + annotationDesc.annotationType().getRawCommentText());
// }
// }
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!