使用Swagger的时候,就有这样一个想法:代码中本身就有一套注释,为啥还要引入一套注解,这不是在做重复的工作么?
javadoc用于解析代码中的注释(不是注解),但是存在一个很大的问题,.java编译成.class文件之后,代码中的注释会被清空,
所以说,项目打包之后,就无法再进行注释解析工作,使用的时候,需要认真思考,自己的需求是什么。
“项目打包之前,忘记生成文档”或者“项目发布之后,更新了代码”,都可能会导致文档与实际不符。
项目中加入tools.jar(java jdk里面复制即可)
<!--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()); // } // }
javadoc用于解析代码中的注释(不是注解),但是存在一定的弊端,.java编译成.class文件之后,代码中的注释会被清空,所以说,项目打包之后,就无法再进行注释解析工作。“项目打包之前,忘记生成文档”或者“项目发布之后,更新了代码”,都可能会导致文档与实际不符。
项目中加入tools.jar(java jdk里面复制即可)
<!--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());// }// }