实现javadoc自定义输出——doclet

来源:互联网 发布:有耽美小说的软件 编辑:程序博客网 时间:2024/05/09 18:52

什么是doclet

doclet可以代替javadoc的输出,借由javadoc可以获取源码几乎所有的信息,类名、类变量、类方法、方法参数、注解、javadoc注释等都可以获取到,然后根据自己的需要把关心的信息输出成自定的格式。

一个简单的doclet类

一个简单的doclet类只需要实现 public static boolean start(RootDoc root) 方法,就可以被javadoc所使用。

package com.hc.ExampleDoclet;import com.sun.javadoc.*;public class ExampleDoclet extends Doclet {    public static boolean start(RootDoc root) {        ClassDoc[] classes = root.classes();        for (ClassDoc cls : classes) {            System.out.println(cls);            MethodDoc[] methods = cls.methods();            for (MethodDoc meth : methods) {                System.out.println(meth);            }        }        return true;    }}

编译之前需要添加tools.jar库到项目中:
tools.jar在jdk下可以找到,如:
D:\Program Files\Java\jdk1.8.0_66\lib\tools.jar。

在eclipse中添加方法如下:
Project -> Properties -> Java Build Path -> Libraries -> Add External Jars
选中tools.jar即可。


执行命令:

>javadoc -doclet com.hc.ExampleDoclet.ExampleDoclet -docletpath bin/ .\src\com\hc\ExampleDoclet\ExampleDoclet.java

输出结果:

正在加载源文件.\src\com\hc\ExampleDoclet\ExampleDoclet.java...正在构造 Javadoc 信息...com.hc.ExampleDoclet.ExampleDocletcom.hc.ExampleDoclet.ExampleDoclet.start(com.sun.javadoc.RootDoc)

如果出现以下信息,只需要把tools.jar添加到CLASSPATH路径即可,tools.jar一般在jdk目录的lib下,也可以在javadoc中指定classpath:

>javadoc -classpath "%JAVA_HOME%/../lib/tools.jar" -doclet com.hc.ExampleDoclet.ExampleDoclet -docletpath bin/ .\src\com\hc\ExampleDoclet\ExampleDoclet.java

向Doclet内传入选项

要接受函数需要实现optionLength方法,控制选项跟随的参数个数。

package com.hc.ExampleDoclet;import java.util.HashMap;import java.util.Map;import com.sun.javadoc.*;public class ExampleDoclet extends Doclet {    public static boolean start(RootDoc root) {        String[][] options = root.options();        for (String[] opt : options) {            if (opt[0].equals("-outFile")) {                System.out.println("outFile:" + opt[1]);            } else if (opt[0].equals("-showMessage")) {                System.out.println("showMessage");            }        }        ClassDoc[] classes = root.classes();        for (ClassDoc cls : classes) {            System.out.println(cls);            MethodDoc[] methods = cls.methods();            for (MethodDoc meth : methods) {                System.out.println(meth);            }        }        return true;    }    public static int optionLength(String option) {        Map<String, Integer> options = new HashMap<String, Integer>();        options.put("-outFile", 2);        options.put("-showMessage", 1);        Integer value = options.get(option);        if (value != null) {            return value;        } else {            return 0;        }    }}

执行命令:

>javadoc -classpath "%JAVA_HOME%/../lib/tools.jar" -doclet com.hc.ExampleDoclet.ExampleDoclet -docletpath bin/ -outFile out.xml -showMessage .\src\com\hc\ExampleDoclet\ExampleDoclet.java

输出结果:

正在加载源文件.\src\com\hc\ExampleDoclet\ExampleDoclet.java...正在构造 Javadoc 信息...outFile:out.xmlshowMessagecom.hc.ExampleDoclet.ExampleDocletcom.hc.ExampleDoclet.ExampleDoclet.start(com.sun.javadoc.RootDoc)com.hc.ExampleDoclet.ExampleDoclet.optionLength(java.lang.String)

获取泛型内的类型

需要获取泛型的类型,需要先实现如下方法到Doclet类,否则将获取不到泛型内的类型!

 public static LanguageVersion languageVersion() {       return LanguageVersion.JAVA_1_5; }

获取泛型的代码:

static List<String> getGenTypeNames(Type typ) {    if (typ instanceof ParameterizedType) {        List<String> ret = new ArrayList<String>();        ParameterizedType pt = typ.asParameterizedType();        Type[] typeArgs = pt.typeArguments();        for (Type t : typeArgs) {            ret.add(t.typeName());        }        return ret;    }    return null;}

获取私有类、私有属性、私有方法

获取私有属性和私有方法可以通过传入参数实现

public static boolean start(RootDoc root) {    ClassDoc[] classes = root.classes();    for (ClassDoc cls : classes) {        System.out.println(cls);        FieldDoc[] fields = cls.fields(false); // 获取包含私有属性在内的所有属性        for (FieldDoc flc : fields) {            System.out.println(flc);        }        MethodDoc[] methods = cls.methods(false);  // 获取包含私有方法在内的所有方法        for (MethodDoc meth : methods) {            System.out.println(meth);        }    }    return true;}

而获取私有类只能通过传入-private选项给javadoc实现。


在maven内使用doclet

编译:

使用maven编译doclet需要添加tools.jar的依赖:

<dependency>     <groupId>com.sun</groupId>     <artifactId>tools</artifactId>     <version>1.8.0</version>     <scope>system</scope>     <systemPath>${java.home}/../lib/tools.jar</systemPath>  </dependency> 

编译doclet:

>mvn compile install

使用:

通过指定doclet路径的方式执行:

>mvn javadoc:javadoc -Ddoclet=com.hc.ExampleDoclet.ExampleDoclet -DdocletPath="${basedir}\target\ExampleDoclet-1.0.0.jar" -DuseStandardDocletOptions=false

需要注意几点:

  • -DdocletPath 小心写成 -Ddocletpath
  • docletPath的起始路径并非项目路径
  • 如果有自定义的选项,可以通过 “-D option=value” 的方式传入
  • 如果没有加上 -DuseStandardDocletOptions=false 会出现错误
    ” Exit code: 1 - javadoc: 错误 - 无效的标记: -author”

把doclet配置到pom之中,并且使用groupId artifactId 定位doclet,在pom.xml加入:

  <build>    <plugins>    <plugin>      <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-javadoc-plugin</artifactId>        <configuration>          <doclet>com.hc.ExampleDoclet.ExampleDoclet</doclet>          <!-- <docletPath>${basedir}\target\ExampleDoclet-1.0.0.jar</docletPath> -->          <docletArtifact>              <groupId>com.hc</groupId>              <artifactId>ExampleDoclet</artifactId>              <version>1.0.0</version>          </docletArtifact>          <useStandardDocletOptions>false</useStandardDocletOptions>        </configuration>      </plugin>    </plugins>  </build>

如果需要传入自定义选项可以通过<additionalparam>传入:

        <configuration>          <doclet>com.hc.ExampleDoclet.ExampleDoclet</doclet>          <!-- <docletPath>${basedir}\target\ExampleDoclet-1.0.0.jar</docletPath> -->          <docletArtifact>              <groupId>com.hc</groupId>              <artifactId>ExampleDoclet</artifactId>              <version>1.0.0</version>          </docletArtifact>          <useStandardDocletOptions>false</useStandardDocletOptions>          <additionalparam>            -outFile out.xml            -showMessage           </additionalparam>        </configuration>

执行命令:

>mvn javadoc:javadoc

执行结果:

[INFO] Scanning for projects...[WARNING][WARNING] Some problems were encountered while building the effective model for com.hc:ExampleDoclet:jar:1.0.0[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-javadoc-plugin is missing. @ line 27, column 10[WARNING][WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.[WARNING][WARNING] For this reason, future Maven versions might no longer support building such malformed projects.[WARNING][INFO][INFO] ------------------------------------------------------------------------[INFO] Building ExampleDoclet 1.0.0[INFO] ------------------------------------------------------------------------[INFO][INFO] >>> maven-javadoc-plugin:2.10.4:javadoc (default-cli) @ ExampleDoclet >>>[INFO][INFO] <<< maven-javadoc-plugin:2.10.4:javadoc (default-cli) @ ExampleDoclet <<<[INFO][INFO] --- maven-javadoc-plugin:2.10.4:javadoc (default-cli) @ ExampleDoclet ---[INFO]正在加载程序包com.hc.ExampleDoclet的源文件...正在构造 Javadoc 信息...outFile:out.xmlshowMessagecom.hc.ExampleDoclet.ExampleDocletcom.hc.ExampleDoclet.ExampleDoclet.start(com.sun.javadoc.RootDoc)com.hc.ExampleDoclet.ExampleDoclet.optionLength(java.lang.String)[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 2.157s[INFO] Finished at: Sat Dec 24 22:17:02 CST 2016[INFO] Final Memory: 12M/153M[INFO] ------------------------------------------------------------------------

在其他PC中使用

由于tools.jar是指定系统位置,在其他PC中使用有可能会存在问题,而我的做法是把tools.jar安装到本地maven库中,然后再通过maven-assembly-plugin插件把tools.jar跟doclet.jar打包到一起。

把tools.jar安装到本地maven库:

>mvn install:install-file -Dfile=tools.jar -DgroupId=com.sun -DartifactId=tools -Dversion=1.8.0 -Dpackaging=jar -DgeneratePom=true

doclet的pom.xml:

    <dependency>          <groupId>com.sun</groupId>          <artifactId>tools</artifactId>          <version>1.8.0</version>          <!--         <scope>system</scope>          <systemPath>${java.home}/../lib/tools.jar</systemPath>          -->     </dependency>  
0 0