写文档
作为一名开发者,每个人都要写代码。
工作中,简直每一位开发者都要写文档。
因为工作是人和人的合作,产品要写需要文档,开发要写具体设计文档,接口文档。
可是,作为一个懒人,平时最厌恶的一件事件就是写文档。
写文档最令我不爽的中央是在于 代码备注要改一遍,而后文档再改一遍。
所有反复的劳作,都是对于咱们贵重摸鱼工夫的最大节约。
于是,我就经常想,能不能只写一遍呢?
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 文档始终是一个大问题。
很多我的项目不写文档,即便写文档,对于开发人员来说也是十分苦楚的。
不写文档的毛病自不必多少,手动写文档的毛病也不言而喻:
- 十分浪费时间,而且会出错。
- 无奈保障及时更新。代码曾经变了,然而文档还要同步批改。须要强制人来保护这一种一致性。这很难。
为什么不是 swagger-ui
java 的文档有几类:
- jdk 自带的 doc 生成。这个以前实际给他人用过,他人用 C#,看到 java 的默认文档感觉很苦楚。
就算是咱们 java 开发者,也很厌恶看 jdk 的文档。看着不美观,也很累。
- swagger-ui 是基于 java 注解的文档生成工具。相对而言比拟优雅,也十分弱小。
然而毛病也是有的。开发人员要写 jdk 原来的正文 + 注解。注解太多,导致写起来也很苦楚,大部分开发者起初还是抉择了放弃。
那么问题来了?咱们怎么办能力尽可能的让开发人员,和文档浏览人员都乐于承受呢?
jdk 自带的 doc 就是基于 maven 插件的,本我的项目也是。
区别如下:
- 尽可能的保障和 Java 原生正文统一,让开发者很容易就能够应用。
- 尽可能的信息全面,然而文档简洁。让文档的阅读者享受到等同于手写文档的体验。
- 将信息的获取和生成辨别开。不便用户本人定义本人的输入形式。
参数配置阐明
为了更加灵便的实现文档的生成和文档元数据的生成,提供如下参数
插件配置属性简介
属性 | 是否必填 | 阐明 | 默认值 | 备注 |
---|---|---|---|---|
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~