写文档

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

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

因为工作是人和人的协作,产品要写需求文档,开发要写详细设计文档,接口文档。

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

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

所有重复的劳作,都是对于我们宝贵摸鱼时间的最大浪费。

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

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~

java 文档自动生成的神器 idoc的更多相关文章

  1. Word 2010文档自动生成目录和某页插入页码

    一.Word 2010文档自动生成目录 关于Word文档自动生成目录一直是我身边同学们最为难的地方,尤其是毕业论文,经常因为目录问题,被要求修改,而且每次修改完正文后,目录的内容和页码可能都会发生变化 ...

  2. springboot成神之——swagger文档自动生成工具

    本文讲解如何在spring-boot中使用swagger文档自动生成工具 目录结构 说明 依赖 SwaggerConfig 开启api界面 JSR 303注释信息 Swagger核心注释 User T ...

  3. VS文档自动生成

    VS2008文档自动生成 (发现,Sandcastle主要是用于C#项目.里面的注释都是XML格式的.不太适合VC的.最终还是得用Doxygen) 一.Sandcastle简介: Sandcastle ...

  4. django接口文档自动生成

    django-rest_framework接口文档自动生成 只针对用到序列化和返序列化 一般还是用第三方yipi 一.安装依赖 pip3 install coreapi 二.设置 setting.py ...

  5. 优于 swagger 的 java markdown 文档自动生成框架-01-入门使用

    设计初衷 节约时间 Java 文档一直是一个大问题. 很多项目不写文档,即使写文档,对于开发人员来说也是非常痛苦的. 不写文档的缺点自不用多少,手动写文档的缺点也显而易见: 非常浪费时间,而且会出错. ...

  6. 如何让接口文档自动生成,SpringBoot中Swagger的使用

    目录 一.在SpringBoot项目中配置Swagger2 1.pom.xml中对Swagger2的依赖 2.编写配置类启用Swagger 3.配置实体类的文档 4.配置接口的文档 5.访问文档 二. ...

  7. Api文档自动生成工具

    java开发,根据代码自动生成api接口文档工具,支持RESTful风格,今天我们来学一下api-doc的生成 作者:互联网编程. 欢迎投稿,一起交流技术 https://www.jianshu.co ...

  8. API的文档自动生成——基于CDIF的SOA基本能力

    当前,作为大部分移动app和云服务后台之间的标准连接方式,REST API已经得到了绝大部分开发者的认可和广泛的应用.近年来,在新兴API经济模式逐渐兴起,许多厂商纷纷将自己的后台业务能力作为REST ...

  9. PDF 补丁丁 0.6.1.3498 版重大更新:为文本PDF文档自动生成书签!

    新的 PDF 补丁丁开放了内部测试了很久的好用功能——自动书签. 这个功能可以在一分钟内快速生成文本型 PDF 文档的书签(说明:本功能分析文档中的文本,生成标题,故对扫描版的 PDF 文档无效). ...

随机推荐

  1. 再过五分钟,你就懂 HTTP 2.0 了!

    Hey guys ,各位小伙伴们大家好,这里是程序员 cxuan,欢迎你收看我最新一期的文章. 这篇文章我们来聊一聊 HTTP 2.0,以及 HTTP 2.0 它在 HTTP 1.1 的基础上做了哪些 ...

  2. pixhawk入门

    PX4 是软件名称,代码约30万行 Pixhawk是硬件名称 MissionPlanner是地面站名称 常见术语: WP:Way Point 航电 geofence:地理围栏 Rally Point: ...

  3. Layui引起的对前端的一次记录

    前言 首先会做这次记录,也是因为自己也是第一次去接触这个框架,以前总是听说,并没有去用过.这次出于实习的原因,去学习了一下Layui这个"面向后端开发者的框架".其次,此篇记录仅供 ...

  4. JavaScript高级程序设计(读书笔记)之函数表达式

    定义函数的方式有两种:一种是函数声明,另一种就是函数表达式. 函数声明的一个重要特征就是函数声明提升(function declaration hoisting),意思是在执行代码前会先读取函数声明. ...

  5. golang channel原理

    channel介绍 channel一个类型管道,通过它可以在goroutine之间发送和接收消息.它是Golang在语言层面提供的goroutine间的通信方式. 众所周知,Go依赖于称为CSP(Co ...

  6. vue post 请求 是 request payload 而不是 FromData ,以及 格式转换成 FromData 需要的 key value 格式

    export function 方法名字(传进来要给后端的参数){     return request({         url : ' 后端提供的接口路径  ',         method  ...

  7. 【SpringMVC】HttpMessageConverter报文信息转换器

    HttpMessageConverter HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报文 HttpMessageConverte ...

  8. Python - 面向对象编程 - self 参数

    为什么要讲 self 参数 class PoloBlog: def __init__(self): ... def say(self): ... 在类里面,所有实例方法都需要加 self 参数,且排在 ...

  9. 数据结构(c++)(第二版) Dijkstra最短路径算法 教学示范代码出现重大问题!

    前言 去年在数据结构(c++)的Dijkstra教学算法案例中,发现了一个 bug 导致算法不能正常的运行,出错代码只是4行的for循环迭代代码. 看到那里就觉得有问题,但书中只给了关键代码的部分,其 ...

  10. Spring表达式

    一.SpEL 其中,直接写也可以赋值,' ' 单引号引起来后成为一个字符串对象,可以调用String的方法: 二.引用另外一个bean 装配这个类的bean: 1.第一种方法,property标签中使 ...