乐趣区

关于github:java-文档自动生成的神器-idoc

写文档

作为一名开发者,每个人都要写代码。

工作中,简直每一位开发者都要写文档。

因为工作是人和人的合作,产品要写需要文档,开发要写具体设计文档,接口文档。

可是,作为一个懒人,平时最厌恶的一件事件就是写文档。

写文档最令我不爽的中央是在于 代码备注要改一遍,而后文档再改一遍。

所有反复的劳作,都是对于咱们贵重摸鱼工夫的最大节约。

于是,我就经常想,能不能只写一遍呢?

i-doc 我的项目简介

idoc 为 java 我的项目生成我的项目文档。

基于原生的 java 正文,尽可能的生成简介的文档。用户能够自定义本人的模板,生成本人须要的文档。

实现原理:基于 maven 插件,相似于 javadoc。能够更加灵便,容许用户自定义。

个性

(1)基于 maven 我的项目生成蕴含大部分信息的元数据

(2)默认反对 markdown 简化文档的生成,反对自定义模板

(3)反对用户自定义文档生成器

(4)反对用户自定生成文档的类过滤器

(5)增加字段类型别名,反对用户自定义

疾速入门

须要

jdk1.8+

maven 3.x+

maven 引入

应用 maven 引入以后 idoc 插件。

<build>
    <plugins>
        <plugin>
            <groupId>com.github.houbb</groupId>
            <artifactId>idoc-core</artifactId>
            <version>0.3.0</version>
        </plugin>
    </plugins>
</build>

测试对象的创立

为了演示文档,咱们创立了一个 Address 对象。

package com.github.houbb.idoc.test.model;

/**
 * 地址
 * @author binbin.hou
 * @since 0.0.1
 */
public class Address {

    /**
     * 城市
     */
    private String country;

    /**
     * 街道
     */
    private String street;

    public String getCountry() {return country;}

    public void setCountry(String country) {this.country = country;}

    public String getStreet() {return street;}

    public void setStreet(String street) {this.street = street;}
}

执行插件

mvn com.github.houbb:idoc-core:0.3.0:idoc

命令行日志信息

[INFO] ------------------------------------ Start generate doc
[INFO] 共计【1】个文件待处理,请急躁期待。进度如下:==================================================================================================== 100%
[INFO] Generator doc with docGenerator: com.github.houbb.idoc.core.api.generator.ConsoleDocGenerator
[INFO] ------------------------------------ 文档信息如下:[类名] com.github.houbb.idoc.test.model.Address
[类信息] {"comment":"地址","docAnnotationList":[],"docFieldList":[{"comment":"城市","name":"country","type":"java.lang.String"},{"comment":"街道","name":"street","type":"java.lang.String"}],"docMethodList":[{"docMethodParameterList":[],"docMethodReturn":{"fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"getCountry","seeList":[],"signature":"getCountry()"},{"docMethodParameterList":[{"docAnnotationList":[],"name":"country","type":"java.lang.String"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"setCountry","seeList":[],"signature":"setCountry(country)"},{"docMethodParameterList":[],"docMethodReturn":{"fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"getStreet","seeList":[],"signature":"getStreet()"},{"docMethodParameterList":[{"docAnnotationList":[],"name":"street","type":"java.lang.String"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"setStreet","seeList":[],"signature":"setStreet(street)"}],"docTagList":[{"lineNum":5,"name":"author","parameters":["binbin.hou"],"value":"binbin.hou"},{"lineNum":6,"name":"since","parameters":["0.0.1"],"value":"0.0.1"}],"fullName":"com.github.houbb.idoc.test.model.Address","modifiers":["public"],"name":"Address","packageName":"com.github.houbb.idoc.test.model"}

[INFO] ------------------------------------ Finish generate doc

更多生成形式

当然,你能够发现这里只是把元数据进行输入到控台,意义不大。

咱们能够依据需要,自定义实现生成类。

比方上面的形式,能够应用内置的 MarkdownDocGenerator 输入到 markdown 文件。

<plugin>
    <groupId>com.github.houbb</groupId>
    <artifactId>idoc-core</artifactId>
    <version>0.3.0</version>
    <configuration>
        <generates>
            <generate>com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator</generate>
        </generates>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>com.github.houbb</groupId>
            <artifactId>idoc-ftl</artifactId>
            <version>0.3.0</version>
        </dependency>
    </dependencies>
</plugin>

成果能够参考:

heaven 文档目录

ps: heaven 我的项目是集体整顿了多年的工具包,几百个类,手写文档预计要很久。

设计初衷

节约工夫

Java 文档始终是一个大问题。

很多我的项目不写文档,即便写文档,对于开发人员来说也是十分苦楚的。

不写文档的毛病自不必多少,手动写文档的毛病也不言而喻:

  1. 十分浪费时间,而且会出错。
  2. 无奈保障及时更新。代码曾经变了,然而文档还要同步批改。须要强制人来保护这一种一致性。这很难。

为什么不是 swagger-ui

java 的文档有几类:

  1. jdk 自带的 doc 生成。这个以前实际给他人用过,他人用 C#,看到 java 的默认文档感觉很苦楚。

就算是咱们 java 开发者,也很厌恶看 jdk 的文档。看着不美观,也很累。

  1. swagger-ui 是基于 java 注解的文档生成工具。相对而言比拟优雅,也十分弱小。

然而毛病也是有的。开发人员要写 jdk 原来的正文 + 注解。注解太多,导致写起来也很苦楚,大部分开发者起初还是抉择了放弃。

那么问题来了?咱们怎么办能力尽可能的让开发人员,和文档浏览人员都乐于承受呢?

jdk 自带的 doc 就是基于 maven 插件的,本我的项目也是。

区别如下:

  1. 尽可能的保障和 Java 原生正文统一,让开发者很容易就能够应用。
  2. 尽可能的信息全面,然而文档简洁。让文档的阅读者享受到等同于手写文档的体验。
  3. 将信息的获取和生成辨别开。不便用户本人定义本人的输入形式。

参数配置阐明

为了更加灵便的实现文档的生成和文档元数据的生成,提供如下参数

插件配置属性简介

属性 是否必填 阐明 默认值 备注
encoding 我的项目编码 UTF-8
includes 元数据蕴含的文件信息 **\/*.java 默认扫描所有 java 文件
excludes 元数据排除的文件信息 默认不排除
isOverwriteWhenExists 文档存在时是否笼罩 true
isAllInOne 所有类信息是否生成单个文档 true 命令行文档生成器,此属性无意义。
generates 文档生成类 命令行文档生成信息 能够同时指定多个。类名全称。用户自定义参见 com.github.houbb.idoc.api.core.genenrator.IDocGenerator
generateFilters 文档生成类过滤器 能够同时指定多个。类名全称。用户自定义参见 com.github.houbb.idoc.api.core.filter.IDocGenerateFilter
targetDir 生成指标文件目录 自定义指定文档生成的文件夹

isAllInOne

简略的文档,倡议间接生成在一个文件。

如果较为简单,则能够设为 false,则会依照

generates 相干问题

默认的命令行文档,次要用于演示和信息查看,不具备实际意义。

倡议引入 idoc-ftl 模块,应用 MarkdownDocGenerator 生成器。

能够同时指定多个。

可引入 idoc-api 自行定义。

generateFilters 倡议

理论的文档,次要关怀定义的办法。

咱们能够针对 DocClass 的包名,过滤只生成 Service 办法文档。

如果是在以前的根底上,则能够加上 @since @version 等信息的过滤。

能够同时指定多个。

可引入 idoc-api 自行定义。

自定义 Filter

能够参考以后我的项目的 idoc-test 模块。

整体配置如下:

<build>
    <plugins>
        <plugin>
            <groupId>com.github.houbb</groupId>
            <artifactId>idoc-core</artifactId>
            <version>0.3.0</version>
            <configuration>
                <isAllInOne>true</isAllInOne>
                <generates>
                    <generate>com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator</generate>
                </generates>
                <generateFilters>
                    <generateFilter>com.github.houbb.idoc.test.filter.MyGenerateFilter</generateFilter>
                </generateFilters>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>com.github.houbb</groupId>
                    <artifactId>idoc-test</artifactId>
                    <version>${project.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

指定文档生成器

指定应用 Markdown 文档生成器,能够同时指定多个。

<generates>
    <generate>com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator</generate>
</generates>

引入包

MarkdownDocGenerator 在 idoc-ftl 模块中,须要引入对应的依赖。

当然 idoc-core 默认依赖 idoc-ftl

指定文件生成类的过滤器

如果不定义本人的类生成过滤器,则会生成所有的类信息。

个别应用中咱们只关怀 service 办法,所以增加了类的过滤实现。

实现如下:

引入 idoc-api 包

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>idoc-api</artifactId>
    <version>${project.version}</version>
</dependency>

实现 IDocGenerateFilter

package com.github.houbb.idoc.test.filter;

import com.github.houbb.idoc.api.core.filter.IDocGenerateFilter;
import com.github.houbb.idoc.api.model.metadata.DocClass;

/**
 * 自定义生成过滤器
 * @author binbin.hou
 * @since 0.0.1
 */
public class MyGenerateFilter implements IDocGenerateFilter {

    @Override
    public boolean include(DocClass docClass) {if("QueryUserService".equalsIgnoreCase(docClass.getName())) {return true;}
        return false;
    }

}

插件中配置应用

<generateFilters>
    <generateFilter>com.github.houbb.idoc.test.filter.MyGenerateFilter</generateFilter>
</generateFilters>

留神,也须要将你定义这个过滤器的 jar 增加依赖,否则无奈找到对应的类信息。

<dependencies>
    <dependency>
        <groupId>com.github.houbb</groupId>
        <artifactId>idoc-test</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

类代码信息

User 信息

/**
 * 用户信息
 * @author binbin.hou
 * @since 0.0.1
 */
public class User {

    /**
     * 名称
     * @require 是
     * @remark 中文名称,请认真填写
     */
    private String name;

    /**
     * 年龄
     */
    private int age;

    /**
     * 生日
     */
    private Date birthday;

    /**
     * 地址
     */
    private List<Address> addressList;

    /**
     * 伴侣
     */
    private User mate;
    
    //...
}

i-doc 定义的标签

@require 示意以后字段是否必填,作为办法入参时。

@remark 示意以后字段的备注信息。

办法类信息

  • QueryUserService.java
/**
 * 查问用户服务类
 * @author binbin.hou
 * @since 0.0.1
 */
public interface QueryUserService {

    /**
     * 依据用户信息查问用户
     * @param user 用户信息
     * @return 后果
     * @since 0.0.2,2019/02/12
     */
    public User queryUser(final User user);

}

执行插件

mvn com.github.houbb:idoc-core:0.3.0:idoc
  • 日志信息
[INFO] ------------------------------------ Start generate doc
[INFO] 共计【4】个文件待处理,请急躁期待。进度如下:==================================================================================================== 100%
[INFO] Generator doc with docGenerator: com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator
[INFO] Markdown 生成文档文件 all in one 门路: /Users/houbinbin/code/_github/idoc/idoc-test/src/main/resources/idoc-gen/idoc-test- 全副文档.md
[INFO] ------------------------------------ Finish generate doc

文档信息

以后文件门路日志会打印,比方我本人测试的为:

/Users/houbinbin/code/_github/idoc/idoc-test/src/main/resources/idoc-gen/idoc-test- 全副文档.md

文档生成成果

参见文档:

idoc-test- 全副文档.md

字段类型别名反对

能够参考以后我的项目的 idoc-test 模块。

为什么须要

有时候页面显示类型,心愿更加敌对。

所以零碎内置了一些别名显示,也同时反对自定义别名。

类型字段的别名

零碎内置

零碎以后版本提供了常见的别名。

详情见 com.github.houbb.idoc.core.util.JavaTypeAliasUtil

类型 别称
java.lang.Float 浮点型
java.lang.Double 浮点型
java.util.Date 日期
java.time.LocalDateTime 日期工夫
java.util.Currency 货币
float 浮点型
java.lang.Integer 整型
long 长整型
java.math.BigDecimal 数字
java.lang.Character 字符
java.lang.Long 长整型
java.lang.Short 短整型
java.util.Map 映射
java.time.LocalTime 工夫
java.lang.Boolean 布尔值
java.math.BigInteger 数字
java.lang.String 字符串
java.lang.Byte 字节
double 浮点型
byte 字节
java.util.Collection 汇合
int 整型
java.util.List 列表
boolean 布尔值
java.time.LocalDate 日期
char 字符
short 短整型
void
array 数组

自定义的形式

能够通过 typeAlias 指定自定义的字段别称。

<configuration>
    <generateFilters>
        <generateFilter>com.github.houbb.idoc.test.filter.MyGenerateFilter</generateFilter>
    </generateFilters>
    <isAllInOne>true</isAllInOne>
    <typeAliases>
        <typeAlias>
            <key>java.lang.String</key>
            <value>String 自定义阐明 </value>
        </typeAlias>
    </typeAliases>
</configuration>

优先级

用户自定义的字段别名优先级高于零碎默认。

前面定义的别名会间接笼罩后面的别名。

测试代码演示

对象定义

/**
 * 别名测试
 * @author binbin.hou
 * @since 0.0.1
 */
public class TypeAliasSimpleBean {

    /**
     * 名称
     */
    private String name;

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}
}

测试日志

运行测试日志如下:

{"comment":"别名测试","docAnnotationList":[],"docFieldList":[{"comment":"名称","name":"name","type":"java.lang.String","typeAlias":"String 自定义阐明"}],"docMethodList":[{"docMethodParameterList":[],"docMethodReturn":{"fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"getName","seeList":[],"signature":"getName()"},{"docMethodParameterList":[{"docAnnotationList":[],"name":"name","type":"java.lang.String","typeAlias":"String 自定义阐明"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"setName","seeList":[],"signature":"setName(name)"}],"docTagList":[{"lineNum":5,"name":"author","parameters":["binbin.hou"],"value":"binbin.hou"},{"lineNum":6,"name":"since","parameters":["0.0.1"],"value":"0.0.1"}],"fullName":"com.github.houbb.idoc.test.model.TypeAliasSimpleBean","modifiers":["public"],"name":"TypeAliasSimpleBean","packageName":"com.github.houbb.idoc.test.model"}

其中 typeAlias 就是字段类型的别名,咱们能够用来更加敌对的显示字段信息。

其余的思考

自定义形式的便利性

自定义的形式采纳基于 xml 的形式是比拟不便。

然而数量比拟多的时候就没有那么不便,原本思考增加对应的配置属性接口,衡量下还是应用了 xml 配置的形式。

是否应用 comment 信息?

如果一个字段,没有指定别名,是否应用 comment 信息做代替?

倡议应用,以后版本不做解决。

  • 为什么应用

比起简短的类信息,大部分人更乐于看到解释。

如果是针对同构的零碎(都是 java 语言),则能够了解。

如果是针对异构的零碎(比方前台是 php),则不易于了解。

  • 为什么不解决

大部分的接口都是常见字段, 性价比不高。

可能存在字段没有些 comment 的状况,会导致判断的复杂性。

如果用户不想应用别名

间接批改模板即可,应用原来的字段 type 属性即可。

开源地址

https://github.com/houbb/idoc

当然,这个我的项目还有很长的路要走。

如果喜爱,欢送 fork star~

退出移动版