在前後端分離的今天,爲了保證進度,前後端一般同步進行開發,所以後端需要先給出接口文檔,再寫實現。
經過筆者不斷地尋找寫文檔的優化方案,至少嘗試過以下方式:
- 手寫,如果是代碼還沒開始寫,這種方式可以當作思考的過程,但是後面改起來也不方便;如果代碼寫完了再來寫文檔,就會很自然感覺有點重複性工作了;
- 基於Swagger的註解,雖然能夠自動生成文檔,但是侵入性太強,曾經用過;
- 基於Spring Doc,spring自帶的文檔功能,感覺有點難用,沒試過
但是,今天這款插件也是筆者一直想做的,還是那句話:程序員應該是懶惰的,絕不重複造輪子!
smart-doc 簡介
smart-doc是一個java restful api文檔生成工具,smart-doc顛覆了傳統類似swagger這種大量採用註解侵入來生成文檔的實現方法。 smart-doc完全基於接口源碼分析來生成接口文檔,完全做到零註解侵入,你只需要按照java標準註釋的寫,smart-doc就能幫你生成一個簡易明瞭的markdown 或是一個像GitBook樣式的靜態html文檔。如果你已經厭倦了swagger等文檔工具的無數註解和強侵入污染,那請擁抱smart-doc吧!
下面就來嘗試一下,個人感覺還是很好用的。
smart-doc使用方式
項目結構很簡單,甚至項目都不用跑起來就可以測試,如下:
插件安裝
查看其插件最新版:https://mvnrepository.com/artifact/com.github.shalousun/smart-doc-maven-plugin
然後加入maven插件裏:
<plugin>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>1.0.4</version>
<configuration>
<!--指定生成文檔的使用的配置文件,配置文件放在自己的項目中-->
<configFile>./src/main/resources/smart-doc.json</configFile>
<!--指定項目名稱-->
<projectName>測試DEMO</projectName>
<!--smart-doc實現自動分析依賴樹加載第三方依賴的源碼,如果一些框架依賴庫加載不到導致報錯,這時請使用excludes排除掉-->
<!-- <excludes>-->
<!-- <!–格式爲:groupId:artifactId;參考如下–>-->
<!-- <exclude>com.alibaba:fastjson</exclude>-->
<!-- </excludes>-->
</configuration>
<executions>
<execution>
<!--如果不需要在執行編譯時啓動smart-doc,則將phase註釋掉-->
<phase>compile</phase>
<goals>
<goal>markdown</goal>
</goals>
</execution>
</executions>
</plugin>
填寫配置
也就是smart-doc.json
內容
{
"outPath": "D:\\workspace\\demo\\smart-doc-demo\\doc",
"allInOne": true,
"customResponseFields": [
{
"name": "resultCode",
"desc": "Response code",
"value": "200"
},
{
"name": "resultMsg",
"desc": "錯誤信息",
"value": null
}
],
"requestHeaders": [
{
"name": "token",
"type": "string",
"desc": "存放於cookie的校驗信息",
"required": true,
"since": "-"
}
]
}
這裏的customResponseFields
對應controller的返回值實體:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ResponseResult<T> {
/**
* 狀態碼
*/
private int resultCode;
/**
* 信息
*/
private String resultMsg;
/**
* 時間戳
*/
private Long tid;
/**
* 數據
*/
private T data;
}
如果要在header裏傳參,那就需要requestHeaders
.
完整的配置可以參考文檔
聲明接口並寫註釋
首先要了解Javadoc有哪些註釋?
可以參考:Java 文檔註釋
我們常用來寫接口的也就幾個:
- @author
- @param
- @return
- @since
然後再探討如何寫優美的文檔,這裏官方給了建議:https://www.oracle.com/technetwork/java/javase/documentation/index-137868.html
下面是一個簡單的示例:
import com.jimo.smartdocdemo.model.ResponseResult;
import com.jimo.smartdocdemo.model.User;
import org.springframework.web.bind.annotation.*;
/**
* 用戶API
*
* @author jimo
* @version 1.0.0
*/
@RestController
@RequestMapping("/api/user")
public class UserController {
/**
* 根據id獲取用戶
*
* @param id ID
*/
@GetMapping("/{id}")
public ResponseResult<User> getUser(@PathVariable Integer id) {
return ResponseResult.create(new User(id, "U" + id, "pwd" + id));
}
}
這裏的User對象要說明下:
首先字段要有註釋,就當作解釋參數含義了,同時支持[JSR303]規定的校驗註解.
比如,不能爲空的字段用@NotNull
標註
import javax.validation.constraints.NotNull;
/**
* 用戶實體
*
* @author jimo
* @version 1.0.0
* @date 2020/3/25 20:22
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
/**
* 主鍵id
*/
private Integer id;
/**
* 用戶名
*/
@NotNull
private String username;
/**
* 密碼
*/
@NotNull
private String password;
}
執行插件生成文檔
可以通過命令行執行maven命令:
//生成html
mvn -Dfile.encoding=UTF-8 smart-doc:html
//生成markdown
mvn -Dfile.encoding=UTF-8 smart-doc:markdown
//生成adoc
mvn -Dfile.encoding=UTF-8 smart-doc:adoc
//生成postman json數據
mvn -Dfile.encoding=UTF-8 smart-doc:postman
也可以在IDEA裏執行插件:
效果
需要強調的使用
在實踐中,會遇到2個比較常見的問題
- 需要忽略實體中的某些字段,smart-doc給出的做法是加
@ignore
: 見文檔
/**
* 忽略,非參數
*
* @ignore
*/
private String name;
- 對方法加註釋時,要使用新的註解
@apiNode
,代表詳細內容,這樣在生成html時錨的內容纔不會很多:
/**
* 獲取特徵(只是個簡單的標題)
*
* @param param 參數
* @apiNote 這是一段非常詳細的描述
*/
@PostMapping("/feature")
public ResponseResult<List<NameValue>> getFeature(){}
- 忽略整個controller,目前還沒支持,已經提了issue
總結
- smart-doc是完全基於源碼分析推導出接口結構,所以是零侵入性的;
- 這種先寫接口聲明,再生成文檔,也完全滿足進度要求,畢竟寫文檔也需要花時間,同時還減少了修改,真正的所見即所得;
- 可以讓程序員養成寫註釋的習慣,這是必須寫的,註釋即文檔
- 這個過程可以自動化的
自動化發佈文檔流程
- 生成文檔
- 把文檔傳到服務器
- 如何傳到服務器:手動,代碼上傳(寫個腳本)
- 渲染文檔
- 通過nginx直接渲染:需要手動修改nginx配置,通過目錄區分項目
- 通過後端應用渲染
可以開發自定義功能
將項目創建、上傳、渲染一起實現了
nginx配置
這裏說下nginx的一個location配置代理多個靜態資源:
- 我們用一個目錄來存項目文檔,如果有多個項目,用文件夾名區分:
# pwd
/deploy/doc
# ls
app1 app2
- nginx配置用alias:
location /deploy {
alias /deploy/doc;
index index.html;
proxy_set_header X-Forwarded-Proto $scheme;
error_page 404 /index.html;
}
- 然後訪問app1的文檔就訪問:http://host/deploy/app1