java导出word文档jar_javadoc导出成word文档

本文档介绍了如何使用Java和Javadoc工具,结合自定义Doclet类,从代码注释中批量导出接口文档到Word格式。通过处理RootDoc对象,解析类、方法、字段的注释信息,生成详细的文档。最后,展示了实现这一过程的代码结构和关键类。
摘要由CSDN通过智能技术生成

刚刚上次弄完了一个坑爹的任务,这次我领导又给我一个让人脑瓜子疼的任务了。

基本上客户他在验收我们系统的时候,都会要求我们编写相关的文档,这次也不例外。

只是这次的客户要求我们给出接口文档。不仅是要整个controller的rest接口文档,还要给出service层的接口,连工具类都要有。这不是在为难我胖虎么。

想我辛辛苦苦给全部controller方法都加上了swagger注解,想我辛辛苦苦把整个项目全部方法都加上了完美的javadoc注释,想我关键代码都留了逻辑注释,

为什么还要我给你弄个word文档。

抱怨归抱怨,该干的活还是要干的,谁让这该死的钱真香。

但是要怎么弄呢?这是个很严重的问题,毕竟我的项目方法没一千都有一百,总不能一个个给他Ctrl C + Ctrl V吧,那我的弄到何年何月。

swagger的我可以找工具导出成word文档,可是service层的呢?我的工具类呢?

有没有现成的工具呢?问下度娘,~~~~~~~~~成功摸鱼半天,毫无收获

那能不能像上次那样用正则自己搞呢?试一哈 ~~~~~~~~~~~~~ 成功摸鱼半天,失败了,有些代码的文档注释太坑爹了,方法内用文档注释,搞事情吧,怎么还有部分前面的*号都没了。

idea不是可以导出javadoc文档么?能不能导出word呢?试一哈 ~~~~~~~~~~~~成功摸鱼半天,毫无办法,不过我找到了一个神奇的方法com.sun.tools.javadoc.Main.execute(initAgrs); 有没有觉得很眼熟,没错,这就是jdk自己的javadoc工具。

先让我们来膜拜下前辈的文章:

https://blog.csdn.net/10km/article/details/78252586

原理其实很简单,javadoc 这个jdk的 tools.jar 中的包的类已经帮我们解析好了java文件,我们需要做的仅仅是重写一个Doclet,然后在它里面处理下javadoc给我弄好的RootDoc就行,剩下就只剩操作RootDoc它了。

先看下javadoc这个包先

b85976a12879da7301f835f9262c082f.png

其中我们将直接用到com.sun.tools.javadoc.Main这个类

bcb7b61372a7be3daf3d96816d390ead.png

那我们需要做啥呢?最简单的就3步。

1、调用com.sun.tools.javadoc.Main.execute()这个方法,传入参数

54c540bef9b565ca350037edace100f0.png

2、写一个自己的Doclet类。

951edab21ed16720ae7f127a74641d38.png

3、拿到数据后,自己解析class类型、方法名、类名、方法注释、类注释、字段注释、参数注释............然后爱生成HTML、爱生成Word、爱生成Excel,随你们喜欢。

大概怎么用说完了,展示下我的生成后的效果吧,我没调样式,毕竟用poi操作word真的是难受

26a84f1aa3533dc317750c9fe27bd7bc.png

上代码:

项目结构:(一定要有tools.jar,他在你们jdk的lib目录里,另外POI操作word的相关包要导齐全,不然各种坑)

7b50fa12554d3a7c19851c2148ae6597.png

pom.xml主要就是为了引入POI的包

4.0.0

com.hongcheng

javadoc_generator

0.0.1-SNAPSHOT

jar

javadoc_generator

http://maven.apache.org

UTF-8

1.8

1.8

1.8

org.apache.poi

poi-ooxml

4.0.0

org.apache.poi

poi-scratchpad

4.0.0

ClassComment.java用来保存类数据的实体

packagecom.hongcheng.javadoc_generator.entity;importjava.util.List;/*** java类的相关信息*/

public classClassComment {/**类的全类名*/

privateString className;/**类的简单类名*/

privateString simpleClassName;/**类注释*/

privateString classComment;/**字段相关信息*/

private Listfields;/**方法相关信息*/

private Listmethods;publicString getClassName() {returnclassName;

}publicString getSimpleClassName() {returnsimpleClassName;

}publicString getClassComment() {returnclassComment;

}public ListgetFields() {returnfields;

}public ListgetMethods() {returnmethods;

}public voidsetClassName(String className) {this.className =className;

}public voidsetSimpleClassName(String simpleClassName) {this.simpleClassName =simpleClassName;

}public voidsetClassComment(String classComment) {this.classComment =classComment;

}public void setFields(Listfields) {this.fields =fields;

}public void setMethods(Listmethods) {this.methods =methods;

}

@OverridepublicString toString() {return "{className: " + className + ", simpleClassName: " + simpleClassName + ", classComment: " +classComment+ ", fields: " + fields + ", methods: " + methods + "}";

}

}

FieldComment.java用来保存字段和参数的实体

packagecom.hongcheng.javadoc_generator.entity;/*** java类中字段的相关信息*/

public classFieldComment {/**字段类型*/

privateString clasz;/**类的简单类名*/

privateString simpleClassName;/**字段注释*/

privateString fieldComment;/**字段名*/

privateString fieldName;/**默认值,必须是final修饰的基本数据类型及其包装类*/

privateObject defaultValue;publicString getSimpleClassName() {returnsimpleClassName;

}public voidsetSimpleClassName(String simpleClassName) {this.simpleClassName =simpleClassName;

}publicString getClasz() {returnclasz;

}publicString getFieldComment() {returnfieldComment;

}publicString getFieldName() {returnfieldName;

}publicObject getDefaultValue() {returndefaultValue;

}public voidsetClasz(String clasz) {this.clasz =clasz;

}public voidsetFieldComment(String fieldComment) {this.fieldComment =fieldComment;

}public voidsetFieldName(String fieldName) {this.fieldName =fieldName;

}public voidsetDefaultValue(Object defaultValue) {this.defaultValue =defaultValue;

}

@OverridepublicString toString() {return "{clasz: " + clasz + ", simpleClassName: " + simpleClassName + ", fieldComment: " +fieldComment+ ", fieldName: " + fieldName + ", defaultValue: " + defaultValue + "}";

}

}

MethodComment.java用来保存方法数据的实体

packagecom.hongcheng.javadoc_generator.entity;importjava.util.List;/*** java类中方法的相关信息*/

public classMethodComment {/**方法注释*/

privateString methodComment;/**方法名*/

privateString methodName;/**参数*/

private Listparams;/**返回值*/

privateFieldComment returnEntity;publicString getMethodComment() {returnmethodComment;

}publicString getMethodName() {returnmethodName;

}public ListgetParams() {returnparams;

}publicFieldComment getReturnEntity() {returnreturnEntity;

}public voidsetMethodComment(String methodComment) {this.methodComment =methodComment;

}public voidsetMethodName(String methodName) {this.methodName =methodName;

}public void setParams(Listparams) {this.params =params;

}public voidsetReturnEntity(FieldComment returnEntity) {this.returnEntity =returnEntity;

}

@OverridepublicString toString() {return "{methodComment: " + methodComment + ", methodName: " + methodName + ", params: " +params+ ", returnEntity: " + returnEntity + "}";

}

}

MyDoclet.java很关键的类

packagecom.hongcheng.javadoc_generator;importcom.sun.javadoc.Doclet;importcom.sun.javadoc.RootDoc;/*** 用来获取javadoc解析完成后生成的语法树根节点

**/

public class MyDoclet extendsDoclet {/*** 静态对象,用于接收javadoc解析完成后生成的语法树根节点

* 在后面我们会用他来获取我们需要的数据

**/

private staticRootDoc root;/*** 在javadoc解析完java文件后,生成语法树,然后就会调用这个方法去让Doclet生成doc文档

**/

public static booleanstart(RootDoc rootDoc) {

MyDoclet.root=rootDoc;return true;

}/*** 获取语法树的根节点

**/

public staticRootDoc getRoot() {returnroot;

}

}

Modifier.java用来处理下哪些方法和字段才是我们需要的

packagecom.hongcheng.javadoc_generator;/*** 可见性修饰符

**/

public enumModifier{

PUBLIC,PROTECTED,PRIVATE;

}

RootClassParser.java用来解析RootDoc,转成我们自己的那三个实体类

packagecom.hongcheng.javadoc_generator;importjava.util.LinkedList;importjava.util.List;importcom.hongcheng.javadoc_generator.entity.ClassComment;importcom.hongcheng.javadoc_generator.entity.FieldComment;importcom.hongcheng.javadoc_generator.entity.MethodComment;importcom.sun.javadoc.ClassDoc;importcom.sun.javadoc.FieldDoc;importcom.sun.javadoc.MethodDoc;importcom.sun.javadoc.ParamTag;importcom.sun.javadoc.Parameter;importcom.sun.javadoc.RootDoc;importcom.sun.javadoc.Tag;/*** RootClass对象的解析器,用于根据RootClass构建我们自己的ClassComment

**/

public classRootClassParser {/**需要处理的类字段可见性,默认公有*/

private Modifier fieldModifier =Modifier.PUBLIC;/**需要处理的类方法可见性,默认公有*/

private Modifier methodModifier =Modifier.PUBLIC;publicRootClassParser(Modifier fieldModifier,Modifier methodModifier) {this.fieldModifier =fieldModifier;this.methodModifier =methodModifier;

}/*** 解析

**/

public Listparse(RootDoc root) {if(root == null) {return new LinkedList();

}

List classComments = new LinkedList();

ClassDoc[] classes=root.classes();for(ClassDoc clasz:classes) {

ClassComment classComment= newClassComment();

classComment.setClassName(clasz.qualifiedTypeName());

classComment.setSimpleClassName(clasz.simpleTypeName());

classComment.setClassComment(clasz.commentText());

classComment.setFields(this.parseFields(clasz.fields()));

classComment.setMethods(this.parseMethods(clasz.methods()));

classComments.add(classComment);

}returnclassComments;

}/*** 解析字段

**/

private ListparseFields(FieldDoc[] fields){if(fields == null || fields.length <= 0) {return new LinkedList();

}

List fieldList = new LinkedList();for(FieldDoc field : fields) {if(!this.checkModifier(field)) {continue;

}

FieldComment fieldComment= newFieldComment();

fieldList.add(fieldComment);

fieldComment.setClasz(field.type().qualifiedTypeName());

fieldComment.setSimpleClassName(field.type().simpleTypeName());

fieldComment.setFieldComment(field.commentText());

fieldComment.setFieldName(field.name());

fieldComment.setDefaultValue(field.constantValue());

}returnfieldList;

}/*** 检查字段修饰语,也就是public、protected、private

*@return如果该字段的访问权限修饰语满足我们需要的级别,那就返回true

**/

private booleancheckModifier(FieldDoc field) {if(this.getFieldModifier().toString().equalsIgnoreCase(field.modifiers())) {return true;

}return false;

}/*** 检查方法修饰语,也就是public、protected、private

*@return如果该方法的访问权限修饰语满足我们需要的级别,那就返回true

**/

private booleancheckModifier(MethodDoc method) {if(this.getMethodModifier().toString().equalsIgnoreCase(method.modifiers())) {return true;

}return false;

}/*** 解析方法

**/

private ListparseMethods(MethodDoc[] methods){if(methods == null || methods.length <= 0) {return new LinkedList();

}

List methodsList = new LinkedList();for(MethodDoc method : methods) {if(!this.checkModifier(method)) {continue;

}

MethodComment methodComment= newMethodComment();

methodsList.add(methodComment);

methodComment.setMethodComment(method.commentText());

methodComment.setMethodName(method.name());

methodComment.setReturnEntity(this.parseMethodReturn(method));

methodComment.setParams(this.parseMethodParam(method));

}returnmethodsList;

}/***

* 解析方法的返回值

**/

privateFieldComment parseMethodReturn(MethodDoc method){//返回值

FieldComment returnEntity = newFieldComment();

returnEntity.setClasz(method.returnType().qualifiedTypeName());

returnEntity.setSimpleClassName(method.returnType().simpleTypeName());for(Tag tag:method.tags()) {if(tag.name().equals("@return")) {

returnEntity.setFieldComment(tag.text());break;

}

}returnreturnEntity;

}/***

* 解析方法的参数

**/

private ListparseMethodParam(MethodDoc method){//参数

List params = new LinkedList();for(Parameter parameter:method.parameters()) {

FieldComment param= newFieldComment();

param.setClasz(parameter.type().qualifiedTypeName());

param.setSimpleClassName(parameter.type().simpleTypeName());

param.setFieldName(parameter.name());for(ParamTag paramTag :method.paramTags()) {if(paramTag.parameterName().equals(param.getFieldName())) {

param.setFieldComment(paramTag.parameterComment());;break;

}

}

params.add(param);

}returnparams;

}publicModifier getFieldModifier() {returnfieldModifier;

}publicModifier getMethodModifier() {returnmethodModifier;

}public voidsetFieldModifier(Modifier fieldModifier) {this.fieldModifier =fieldModifier;

}public voidsetMethodModifier(Modifier methodModifier) {this.methodModifier =methodModifier;

}

}

WordExport.java用来生成word文档的

packagecom.hongcheng.javadoc_generator;importjava.io.FileOutputStream;importjava.util.List;importorg.apache.poi.xwpf.usermodel.TableWidthType;importorg.apache.poi.xwpf.usermodel.XWPFDocument;importorg.apache.poi.xwpf.usermodel.XWPFParagraph;importorg.apache.poi.xwpf.usermodel.XWPFTable;importorg.apache.poi.xwpf.usermodel.XWPFTableCell;importorg.apache.poi.xwpf.usermodel.XWPFTableRow;importorg.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;importcom.hongcheng.javadoc_generator.entity.ClassComment;importcom.hongcheng.javadoc_generator.entity.FieldComment;importcom.hongcheng.javadoc_generator.entity.MethodComment;public classWordExport {public void export(List result,String path) throwsException {

XWPFDocument xwpfDocument= this.newWord();for(ClassComment classComment: result) {this.newParagraph(xwpfDocument, "类名:" +classComment.getClassName());this.newParagraph(xwpfDocument, "说明:" +classComment.getClassComment());//字段

if(classComment.getFields() != null && !classComment.getFields().isEmpty()) {

XWPFTable table= this.newTable(xwpfDocument, classComment.getFields().size() + 3, 5);this.mergeCell(table.getRow(0), 0, 4, "类名:" +classComment.getClassName());this.mergeCell(table.getRow(1), 0, 4, "属性:");this.setTableRowText(table.getRow(2), 0, 4, "序号","参数类型","参数名","常量值","说明");this.setCellWidth(table.getRow(2), 0, 4, "10%","22.5%","22.5%","22.5%","22.5%");for(int i = 0,j = 3;i < classComment.getFields().size();i++,j++) {

FieldComment field=classComment.getFields().get(i);this.setTableRowText(table.getRow(j), 0, 4, String.valueOf(i + 1)

,field.getSimpleClassName()

,field.getFieldName()

,field.getDefaultValue()== null?"":field.getDefaultValue().toString()

,field.getFieldComment());

}this.newBlankLine(xwpfDocument);this.newBlankLine(xwpfDocument);

}//方法

if(classComment.getMethods() != null && !classComment.getMethods().isEmpty()) {for(MethodComment method: classComment.getMethods()) {

XWPFTable table= this.newTable(xwpfDocument, 3, 4);this.mergeCell(table.getRow(0), 0, 3, "类名:" +classComment.getClassName());this.mergeCell(table.getRow(1), 0, 3, "方法名:" +method.getMethodName());this.mergeCell(table.getRow(2), 0, 3, "方法说明:" +method.getMethodComment());//参数

if(method.getParams() == null ||method.getParams().isEmpty()) {this.mergeCell(table.createRow(), 0, 3, "参数:无");

}else{this.mergeCell(table.createRow(), 0, 3, "参数:");this.setTableRowText(table.createRow(), 0, 3, "序号","参数类型","参数名","说明");this.setCellWidth(table.getRow(table.getRows().size()-1), 0, 3, "10%","25%","25%","40%");for(int i = 0;i < method.getParams().size(); i++) {

FieldComment field=method.getParams().get(i);this.setTableRowText(table.createRow(), 0, 3, String.valueOf(i + 1)

,field.getSimpleClassName()

,field.getFieldName()

,field.getFieldComment());

}

}//返回值

this.mergeCell(table.createRow(), 0, 3, "返回值:" + method.getReturnEntity().getSimpleClassName() + " " +method.getMethodComment());this.newBlankLine(xwpfDocument);this.newBlankLine(xwpfDocument);

}

}this.newBlankLine(xwpfDocument);this.newBlankLine(xwpfDocument);this.newBlankLine(xwpfDocument);this.newBlankLine(xwpfDocument);

}this.writeFile(xwpfDocument, path);

}/*** 设置单元格宽度

*@paramrow

*@paramstartCell 起始单元格下标,row的单元格下标从0开始

*@paramendCell 结束单元格下标

*@parampercentages 各个单元格的百分百大小,例如"25.5%"

**/

private void setCellWidth(XWPFTableRow row,int startCell,intendCell,String ...percentages) {if(percentages == null || percentages.length <= 0) {throw new IllegalArgumentException("percentages不能为空");

}if((endCell - startCell + 1) >percentages.length) {throw new IllegalArgumentException("percentages的元素不够");

}int i = 0;for(XWPFTableCell cell: row.getTableCells()) {

cell.setWidth(String.valueOf(percentages[i++]));

cell.setWidthType(TableWidthType.PCT);

}

}/*** 设置单元格宽度

*@paramrow

*@paramstartCell 起始单元格下标,row的单元格下标从0开始

*@paramendCell 结束单元格下标

*@paramsizes 各个单元格的宽度大小

**/@SuppressWarnings("unused")private void setCellWidth(XWPFTableRow row,int startCell,int endCell,int...sizes) {if(sizes == null || sizes.length <= 0) {throw new IllegalArgumentException("sizes不能为空");

}if((endCell - startCell + 1) >sizes.length) {throw new IllegalArgumentException("sizes的元素不够");

}int i = 0;for(XWPFTableCell cell: row.getTableCells()) {

cell.setWidth(String.valueOf(sizes[i++]));

cell.setWidthType(TableWidthType.DXA);

}

}/*** 跨行合并单元格

*@paramtable

*@paramstartRow 起始行下标,table的行下标从0开始

*@paramendRow 结束行下标

*@paramstartCell 行内起始单元格下标,row的单元格下标从0开始

*@paramendCell 行内结束单元格下标

*@paramtext 合并后的单元格文本

**/@SuppressWarnings("unused")private void mergeRow(XWPFTable table,int startRow,int endRow,int startCell,intendCell,String text) {

List rows =table.getRows();for (int j = startRow; j <= endRow; j++) {

List tableCells =rows.get(j).getTableCells();//对每个单元格进行操作

for (int i = startCell; i <= endCell; i++) {//对单元格进行合并的时候,要标志单元格是否为起点,或者是否为继续合并

if (i ==startCell )

tableCells.get(i).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);elsetableCells.get(i).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);//继续合并

}

}for (int j = startRow; j <= endRow; j++) {

List tableCells =rows.get(j).getTableCells();//对每个单元格进行操作//对单元格进行合并的时候,要标志单元格是否为起点,或者是否为继续合并

if (j ==startRow )

tableCells.get(startCell).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);elsetableCells.get(startCell).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);//继续合并

}

rows.get(startRow).getCell(startCell).setText(text);//为第1行1到4合并之后的单元格设置内容

}/*** 合并表格单元格,针对行内的单元格进行合并

*@paramrow

*@paramstartCell 起始单元格下标,row的单元格下标从0开始

*@paramendCell 结束单元格下标

*@paramtext 合并后的单元格文本

**/

private void mergeCell(XWPFTableRow row,int startCell,intendCell,String text) {

List tableCells =row.getTableCells();//对每个单元格进行操作

for (int i = startCell; i <= endCell; i++) {//对单元格进行合并的时候,要标志单元格是否为起点,或者是否为继续合并

if (i ==startCell)

tableCells.get(i).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);elsetableCells.get(i).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);//继续合并

}

tableCells.get(startCell).setText(text);//为第1行1到4合并之后的单元格设置内容

}/*** 给表格一行赋值,实际设置值是包括首尾单元格的,例如startCell=0,endCell=2,实际会设置0、1、2这三个单元格

*@paramrow

*@paramstartCell 起始单元格下标,row的单元格下标从0开始

*@paramendCell 结束单元格下标

*@paramtexts 单元格的内容,依次赋值

**/

private void setTableRowText(XWPFTableRow row,int startCell,intendCell,String ...texts) {if(texts == null || texts.length <= 0) {throw new IllegalArgumentException("texts不能为空");

}if((endCell - startCell + 1) >texts.length) {throw new IllegalArgumentException("texts的元素不够");

}

List tableCells =row.getTableCells();//对每个单元格进行操作

for (int i = startCell,j = 0; i <= endCell; i++,j++) {

tableCells.get(i).setText(texts[j]);

}

}/*** 创建一个table

*@paramxwpfDocument

*@paramrowNum 行数

*@paramcolNum 列数

**/

private XWPFTable newTable(XWPFDocument xwpfDocument,int rowNum,intcolNum) {

XWPFTable createTable=xwpfDocument.createTable(rowNum, colNum);

createTable.setWidth("100%");

createTable.setWidthType(TableWidthType.PCT);returncreateTable;

}/*** 创建一个文本行

**/

privateXWPFParagraph newParagraph(XWPFDocument xwpfDocument,String text) {

XWPFParagraph createParagraph=xwpfDocument.createParagraph();

createParagraph.createRun().setText(text);returncreateParagraph;

}/*** 创建一个空行

**/

privateXWPFParagraph newBlankLine(XWPFDocument xwpfDocument) {return this.newParagraph(xwpfDocument, "");

}/*** 创建一个word文档

**/

privateXWPFDocument newWord() {

XWPFDocument xwpfDocument= newXWPFDocument();returnxwpfDocument;

}/*** 写文件

**/

private void writeFile(XWPFDocument xwpfDocument,String path) throwsException {

xwpfDocument.write(new FileOutputStream("C:\\Users\\HongCheng\\Desktop\\1.docx"));

xwpfDocument.close();

}

}

JavaDocReader.java用来验证参数以及调用javadoc.Main类的

packagecom.hongcheng.javadoc_generator;importjava.util.Collection;importjava.util.LinkedList;importjava.util.List;importjava.util.Map;importcom.hongcheng.javadoc_generator.entity.ClassComment;importcom.sun.javadoc.RootDoc;/*** java文件doc读取器

**/

public classJavaDocReader {/**用于接收javadoc解析完成后生成的语法树根节点*/

private MyDoclet doclet = newMyDoclet();/**类路径,系统会在类路径下去找一些相关的类文件*/

private Listclasspath ;/**java源文件地址。可以是java源文件的绝对地址,也可以是包名。只能填写一个,*/

privateString sourcepath;/**是否递归处理子包,只有在sourcepath为包名时才起作用,subpackages不为空是才是true。默认false*/

private boolean isSubpackages = false;/**要递归的子包*/

privateString subpackages ;/**需要处理的类字段可见性,默认公有*/

private Modifier fieldModifier =Modifier.PUBLIC;/**需要处理的类方法可见性,默认公有*/

private Modifier methodModifier =Modifier.PUBLIC;/**jdk的tools.jar的地址*/

private String jdkToolsJarPath = JavaDocReader.class.getResource("/").getPath() + "/tools.jar";/*** 构造函数

*@paramjavaPackage 目标jar包,非空必填

*@paramsubpackages 需要递归处理的子包,可以为空

*@paramclassPath 相关的jar包的地址,绝对地址,javaPackage必须要能在这些路径中找到,非空必填

**/

public JavaDocReader(String javaPackage,String subpackages,ListclassPath) {this.init(javaPackage, subpackages, classPath, Modifier.PUBLIC, Modifier.PUBLIC);

}/*** 构造函数

*@paramjavaPackage 目标jar包,非空必填

*@paramsubpackages 需要递归处理的子包,可以为空

*@paramclassPath 相关的jar包的地址,绝对地址,javaPackage必须要能在这些路径中找到,非空必填

*@paramfieldModifier 需要处理的类字段可见性,非空

*@parammethodModifier 需要处理的类方法可见性,非空

**/

public JavaDocReader(String javaPackage,String subpackages,ListclassPath

,Modifier fieldModifier,Modifier methodModifier) {this.init(javaPackage, subpackages, classPath, fieldModifier, methodModifier);

}/*** 构造函数

*@paramjavaFilePath java文件地址,非空必填,绝对路径

*@paramclasspath 源文件中引用的相关类的jar包地址,可选

**/

public JavaDocReader(String javaFilePath,Listclasspath ) {this.init(javaFilePath, null, classpath, Modifier.PUBLIC, Modifier.PUBLIC);

}/*** 构造函数

*@paramjavaFilePath java文件地址,非空必填,绝对路径

*@paramclasspath 源文件中引用的相关类的jar包地址,可选

*@paramfieldModifier 需要处理的类字段可见性,非空

*@parammethodModifier 需要处理的类方法可见性,非空

**/

public JavaDocReader(String javaFilePath,Listclasspath

,Modifier fieldModifier,Modifier methodModifier) {this.init(javaFilePath, null, classpath, fieldModifier, methodModifier);

}/*** 构造函数

*@paramsourcepath .java源文件地址,非空。可以是java源文件的绝对地址,也可以是包名。

* 如果是java源文件的绝对地址,只能填写一个地址,不能填写多个地址。

* 如果是包名,该包必须能在classpath下找到,只能填写一个包名

*@paramclasspath 类路径,系统会在类路径下去找一些相关的类文件,可以为空

*@paramsubpackages 是否递归处理子包,只有在sourcepath为包名时才起作用,可以为空

*@paramfieldModifier 需要处理的类字段可见性,非空

*@parammethodModifier 需要处理的类方法可见性,非空

**/

private void init(String sourcepath,String subpackages,Listclasspath

,Modifier fieldModifier,Modifier methodModifier) {this.checkNotEmpty(sourcepath, "目标java文件不能为空");

classpath= this.checkNotEmpty(classpath)?new LinkedList(classpath):new LinkedList();

classpath.add(this.getJdkToolsJarPath());this.classpath =classpath;this.sourcepath =sourcepath;this.subpackages =subpackages;this.fieldModifier = fieldModifier == null?this.fieldModifier:fieldModifier;this.methodModifier = methodModifier == null?this.methodModifier:methodModifier;this.isSubpackages = this.checkNotEmpty(subpackages);

}/*** 初始化参数

*@returnString [] javadoc需要的参数数组

**/

privateString [] initAgrs() {

List args = new LinkedList();

args.add("-encoding");

args.add("utf-8");

args.add("-doclet");

args.add(MyDoclet.class.getName());

args.add("-docletpath");

args.add(MyDoclet.class.getResource("/").getPath());if(this.isSubpackages()) {

args.add("-subpackages");

args.add(this.getSubpackages());

}

StringBuilder sb= newStringBuilder();for(String classpath: this.getClasspath()) {

sb.append(classpath).append(";");

}if(sb.length() > 0) {

sb.deleteCharAt(sb.length()- 1);

}

args.add("-classpath");

args.add(sb.toString());if(this.fieldModifier == Modifier.PRIVATE || this.methodModifier ==Modifier.PRIVATE) {

args.add("-private");

}else if(this.fieldModifier == Modifier.PROTECTED || this.methodModifier ==Modifier.PROTECTED) {

args.add("-protected");

}else{

args.add("-public");

}

args.add(this.sourcepath);return args.toArray(newString[args.size()]);

}/*** 执行javadoc,解析源文件

**/

private voidexecuteJavadoc() {

String[] initAgrs= this.initAgrs();

com.sun.tools.javadoc.Main.execute(initAgrs);

}/*** 获取类注释信息

*@returnList

**/

public Listexecute(){this.executeJavadoc();

RootDoc root=MyDoclet.getRoot();if(root == null) {return new LinkedList();

}

RootClassParser parser= new RootClassParser(this.getFieldModifier(),this.getMethodModifier());

List parseResult =parser.parse(root);returnparseResult;

}publicString getJdkToolsJarPath() {returnjdkToolsJarPath;

}public voidsetJdkToolsJarPath(String jdkToolsJarPath) {this.jdkToolsJarPath =jdkToolsJarPath;

}publicString getSubpackages() {returnsubpackages;

}public voidsetSubpackages(String subpackages) {this.subpackages =subpackages;

}publicMyDoclet getDoclet() {returndoclet;

}public ListgetClasspath() {returnclasspath;

}publicString getSourcepath() {returnsourcepath;

}public booleanisSubpackages() {returnisSubpackages;

}publicModifier getFieldModifier() {returnfieldModifier;

}publicModifier getMethodModifier() {returnmethodModifier;

}public voidsetDoclet(MyDoclet doclet) {this.doclet =doclet;

}public void setClasspath(Listclasspath) {this.classpath =classpath;

}public voidsetSourcepath(String sourcepath) {this.sourcepath =sourcepath;

}public void setSubpackages(booleanisSubpackages) {this.isSubpackages =isSubpackages;

}public voidsetFieldModifier(Modifier fieldModifier) {this.fieldModifier =fieldModifier;

}public voidsetMethodModifier(Modifier methodModifier) {this.methodModifier =methodModifier;

}

@SuppressWarnings("rawtypes")private voidcheckNotEmpty(Object arg,String exceptionMsg) {if(exceptionMsg == null) {

exceptionMsg= "参数不能为空。";

}if(arg == null) {throw newNullPointerException(exceptionMsg);

}if(arg instanceofString) {

String argStr=(String)arg;if(argStr.isEmpty()) {throw newIllegalArgumentException(exceptionMsg);

}

}else if(arg instanceofCollection) {

Collection collection=(Collection)arg;if(collection.isEmpty()) {throw newIllegalArgumentException(exceptionMsg);

}

}else if(arg instanceofMap) {

Map map=(Map)arg;if(map.isEmpty()) {throw newIllegalArgumentException(exceptionMsg);

}

}

}

@SuppressWarnings("rawtypes")private booleancheckNotEmpty(Object arg) {if(arg == null) {return false;

}if(arg instanceofString) {

String argStr=(String)arg;if(argStr.isEmpty()) {return false;

}

}else if(arg instanceofCollection) {

Collection collection=(Collection)arg;if(collection.isEmpty()) {return false;

}

}else if(arg instanceofMap) {

Map map=(Map)arg;if(map.isEmpty()) {return false;

}

}return true;

}

}

Test.java没啥屁用的测试类,就是来看效果的

packagecom.hongcheng.javadoc_generator;importjava.util.Collections;importjava.util.List;importcom.hongcheng.javadoc_generator.entity.ClassComment;public classTest {public static void main(String[] args) throwsException {

String jarPath= "C:\\Users\\HongCheng\\Desktop\\11.jar";

JavaDocReader javaDocReader= new JavaDocReader( "hongcheng.code_generator","hongcheng.code_generator",Collections.singletonList(jarPath),Modifier.PRIVATE,Modifier.PUBLIC );

List execute =javaDocReader.execute();

WordExport wordExport= newWordExport();

wordExport.export(execute,"C:\\Users\\HongCheng\\Desktop\\1.docx");

}

}

这是javadoc的参数,你也可以自己设置

100f7c87d1b663cb4bc579b20b6ba57b.png

其实这个主要就是在代码中使用javadoc这个工具,原理就是通过javadoc工具去解析目标类/jar,获取到类信息和注释信息后,在按照自己的格式去输出

代码上传码云了,相关jar包也在上面

https://gitee.com/1281003978/javadoc_generator

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值