前言
經過本人的不懈努力,LKADocument終於接近我心目中完美的樣子,不敢說有百分之百,也至少有了百分之九十。前段時間匆忙發佈過兩個版本,可能是因爲界面和存在的BUG,並沒有得到大家的關注和反饋,一度有些失望。但我相信,只要是好東西,總會有發光的一天,LKADocument在我工作當中使用也有大半年時間了,磨合了這麼久,BUG也越來越少了,功能也越來越強大了,使用起來也越來越方便了。借我同事的話說:“這是我用過最好用的接口文檔工具,沒有之一”,哈哈,得到別人的認可確實是一件非常開心的事。但LKADocument必竟是一個新的東西,還沒有接受社會主義市場的毒打,不敢保證大家在使用過程不會出現問題,但是我希望大家在使用過程中能及時反饋這些問題給我,我是真心想把它做得完美,也真心希望它能給大家在工作上帶來便利。
我也不想再把swagger搬出來做比較了,仁者見仁,智者見智,在以前我確實認爲swagger很優秀。但是現在有一個更優秀的接口文檔工具誕生啦!當然我一個人說了不算,直接上乾貨——>教程奉上。
準備工作:
第一步:在項目中引入兩個jar包
<!--LKADocument包-->
<dependency>
<groupId>com.github.liukaitydn</groupId>
<artifactId>lkadocument</artifactId>
<version>1.0.1</version>
</dependency>
<!--itextpdf包,把接口信息導出成PDF文檔是基於itextpdf來實現的,所以要引入這個包-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
第二步:在SpringBoot項目啓動類上加上@LKADocument註解
@SpringBootApplication
@LKADocument //LKADocument接口文檔註解
public class LKADemoApplication {
public static void main(String[] args) {
SpringApplication.run(LKADemoApplication.class, args);
}
}
第三步:基礎配置
#在application.yml文件中添加如下配置:
lkad:
#要掃描接口的包路徑,多個用","號隔開,指定父包可以掃描所有父包下的子包(必配)
basePackages: com.lk.api
#項目名稱(選配)
projectName: LKADocument測試項目
#項目描述(選配)
description: 智能、便捷、高效
#要聚合的項目地址,多個用","號隔開,用來聚合其它項目的接口信息,可以在UI界面切換(選配)
serverNames: 192.168.0.77:9010,192.168.0.77:8888
#項目的版本號(選配)
version: 1.0
#啓動開關,true是開啓,false是禁用,默認爲開啓(選配)
enabled: true
或者在啓動類註解@LKADocument上設置如下屬性(和上面配置二選一即可,效果一模一樣)
@SpringBootApplication
@LKADocument(basePackages="com.lk.api",projectName="LKADocument測試項目",description="智能、便捷、高效",
serverNames="192.168.0.77:9010,192.168.0.77:8888",version="1.0",enabled=true)
public class LKADemoApplication {
public static void main(String[] args) {
SpringApplication.run(LKADemoApplication.class, args);
}
}
第四步:準備一個帶API的測試類(不要被這麼多屬性嚇到哈,大部分屬性都是可以不填的,屬性越多,說明功能越強大嘛!)
(注意:LKADocument爲swagger大部分註解做了兼容處理,只需修改引入的包路徑爲com.lk.api.*即可)
/**
* LKAType註解:用來描述接口對應的處理類
* value:類的作用(必填)
* description:類的描述(選填)
* hidden:是否在UI界面隱藏該類的信息,默認爲false(選填)
*/
@LKAType(value="第一個測式類",description="用來演示LKADocument",hidden=false)
@RestController
@RequestMapping("lkadocument/demo")
public class LKADemoController {
/*
* LKAMethod註解:用來描述接口信息
* value:接口的作用(必填)
* description:接口的描述(選填)
* contentType:請求頭ContentType類型,默認爲application/x-www-form-urlencoded(選填)
* author:作者(選填)
* createTime:接口創建時間(選填)
* updateTime:接口修改時間(選填)
* hidden:是否在UI界面隱藏該接口,默認爲false(選填)
* version:接口版本號,如果項目版本號相同,在UI界面會標記爲新接口(選填)
*/
@LKAMethod(value="登錄1",description="用戶登錄驗證",contentType=ContentType.URLENCODED,
author="liukai",createTime="2020-6-20",updateTime="2020-6-20",hidden=false,version="1.0")
@LKAParam(names= {"name","pwd"},values= {"用戶名","密碼"})
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"})
@PostMapping("login")
public Map<String,Object> login(String name,String pwd) {
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","登錄成功,歡迎"+name+"光臨本系統");
return map;
}
@LKAMethod(value="登錄2")
@LKAParam(names= {"name","pwd"},values= {"用戶名","密碼"})
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"})
@PostMapping("test")
public Map<String,Object> login2(String name,String pwd) {
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","登錄成功,歡迎"+name+"光臨本系統");
return map;
}
}
第五步:打開瀏覽器,輸入地址:http://127.0.0.1:8080/lkadoc.html
登錄1接口信息
切換項目效果(暫不支持其它項目導出PDF文檔,在對其它項目進行數組傳參,文件上傳下載API調試時也會有問題)
導出的PDF接口文檔效果(目前只支持導出本地項目的接口,導出後PDF第一頁下面是有留白給用戶自己添加說明信息)
請求參數基本用法(下面這個方法展示了常見的幾種傳參模式,很具有代表性)
@LKAMethod(value="獲取用戶列表")
/*
* 以下兩種寫法是完全等價的,帶s複數註解代表可以一個註解設置多個參數,但要注意參數順序
* LKAParam註解:用來描述請求參數信息
* name:參數名稱(必填)
* value:參數作用(必填)
* description:參數的描述(選填)
* dataType:參數數據類型,默認String(選填)
* required:是否必傳,默認爲true(選填)
* (更簡便的用法是在參數名後加"-n"代表不是必傳,不加默認是必傳)
* paramType:參數位置,query、header、path三選一,默認爲query(選填)
* isArray:是否是集合或數組,默認false(選填)
* testData:測試數據(選填)
*/
@LKAParam(names= {"name","age-n","roleType-n","token"},
values= {"用戶名","年齡","角色類型","授權token"},
descriptions= {"支持模糊匹配","範圍0-120","1-經理,2-主管,3-普通員工","授權token"},
dataTypes= {"String","int","int","String"},
//requireds= {true,false,false,true},
paramTypes= {ParamType.QUERY,ParamType.QUERY,ParamType.PATH,ParamType.HEADER},
testDatas= {"liu","20","1","38e12c99"},
isArrays= {false})
/*
* @LKAParams({
@LKAParam(name="name",value="用戶名",required=true,description="支持模糊匹配",
dataType="String",paramType=ParamType.QUERY,isArray=false,testData="liu"),
@LKAParam(name="age",value="年齡",required=false,description="範圍0-120",
dataType="int",testData="20"),
@LKAParam(name="roleType-n",value="角色類型",description="1-經理,2-主管,3-普通員工",
dataType="int",paramType=ParamType.PATH,testData="1"),
@LKAParam(name="token",value="授權token",description="授權token",
paramType=ParamType.HEADER,testData="38e12c99")
})*/
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"})
@PostMapping("getUsers/{roleType}")
public Map<String,Object> getUsers(
String name,
Integer age,
@PathVariable("roleType")Integer roleType,//path參數
@RequestHeader("token")String token) { //header參數
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","獲取信息成功!name="+name+",age="+age+",roleType="+roleType+",token="+token);
return map;
}
UI界面信息
當多個接口都需要token授權時,爲了調試方便,可以鎖定token,這樣在調試不同接口時會自動在請求頭帶上這個token
數組傳參
/*
* 數組傳參注意事項
* 1.isArray要設置成true,代表是數組
* 2.dataType參數類型後面要加“[]”
* 3.接口調試時要勾選“阻止深度序列化”
*/
@LKAMethod(value="數組傳參")
@LKAParam(name="ids",value="用戶id",isArray=true,dataType="String[]")
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"})
@PostMapping("arrTest")
public Map<String,Object> arrTest(String[] ids) {
String arr = "";
if(ids != null) {
for (String id : ids) {
arr = arr+","+id;
}
}
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","獲取信息成功!ids="+arr);
return map;
}
數組傳參調試界面
文件上傳
/*
* 文件上傳(支持單個或批量上傳)注意事項
* 1.如果是批量上傳isArray要設置成true,代表是數組
* 2.單個文件上傳dataType類型要設置成"file",批量上傳dataType參數類型要設置成“file[]”
* 3.前端需要把from表單的enctype屬性設置成'multipart/form-data'
* 4.請求類型必須是"post"
*/
@LKAMethod(value="文件批量上傳")
@LKAParam(name= "files",value="上傳文件",isArrays= true,dataType="file[]")
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"})
@PostMapping("fileUpload")
public Map<String,Object> fileUpload(MultipartFile[] files) {
String fileNames = "";
if(files != null) {
for (MultipartFile f : files) {
fileNames = fileNames + ","+f.getOriginalFilename();
}
}
//上傳後續業務處理:略
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","上傳文件成功!,files="+fileNames);
return map;
}
文件上傳調試界面
文件下載(演示下載D盤下的test.pdf文件)
/*
* 文件下載注意事項
* LKAMethod註解裏面的download屬性要設置成true,代表是下載的API
*/
@LKAMethod(value="文件下載",download=true)
@PostMapping("fileDownload")
public void fileDownload(HttpServletResponse response) throws Exception {
String path = "D:\\test.pdf";
File file = new File(path);
String ext = file.getName().substring(file.getName().lastIndexOf(".") + 1).toUpperCase();
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes()));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
toClient.close();
}
文件下載調試界面
複雜的對象傳參
第一步:準備幾個對象用於測試
/**
* LKAModel註解:用來標識需要掃描的實體類
* LKAProperty註解:用來描述實體類的屬性信息
* value:屬性的作用
* description:屬性的描述
* hidden:是否在UI界面隱藏該屬性,默認爲false(選填)
* testData:測試數據
* required:是否必須
* isArray:是否是數組或集合
* type:當屬性爲對象類型時,需用type來指定
*/
@LKAModel
public class User {
@LKAProperty(value="用戶ID",hidden=true)//hidden設置成true,該不會在UI界面展示
private Integer id;
@LKAProperty(value="用戶名稱",testData="張三")
private String name;
@LKAProperty(value="年齡",required=false,description="範圍0-120",testData="22")
private String age;
@LKAProperty(type=Role.class,value="角色對象")
private Role role;
@LKAProperty(value="用戶愛好",isArray=true,testData="運動")
private String[] likes;
@LKAProperty(type=Address.class,isArray=true,value="地址信息")
private List<Address> addresses;
....get/set方法.....
}
@LKAModel
public class Role {
@LKAProperty(value="角色ID",testData="1")
private Integer id;
@LKAProperty(value="角色名稱",testData="經理")
private String name;
....get/set方法.....
}
@LKAModel
public class Address {
@LKAProperty(value="地址ID",testData="5")
private Integer id;
@LKAProperty(value="地址信息",testData="深圳市龍華區")
private String info;
....get/set方法.....
}
第二步:準備測試方法
/*
* 複雜的對象傳參
* 注意事項:
* 1.如果入參是對象,並且對象上定義了@LKAModel註解,無需定義@LKAParam,可以自動被掃描到
* 2.如果接收請求參數對象帶嵌套對象需把contentType屬性設置爲"application/json",
* 3.如果contentType="application/json",需在接收對象前面加@RequestBody註解
*/
@LKAMethod(value="複雜的對象傳參",contentType=ContentType.JSON)
@LKAResposes({
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"}),
@LKARespose(type=User.class,value= "用戶對象")
})
@PostMapping("addUser")
public Map<String,Object> addUser(@RequestBody User user) {
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","操作成功!");
map.put("user",user);
return map;
}
第三步:查看UI調試界面
對象參數分組
我們感受到了用對象接收請求參數更具便利性,那怎麼去過濾對象屬性呢?例如:有一個查詢接口,只用到user對象的name、age和addresses屬性對象的info參數,但對於前端的友好度,我們不需要展示所有對象屬性到UI界面,這時我們就可以用分組來實現
/**
* 因爲該接口只用到了User對象的name、age和addresses.info參數這三個參數,
* 我們可以把這三個參數分爲一組,組名不能夠重複,其它是沒有任何限制的,
* 只需要是合法的字符串即可。爲了區分,你可以用接口名稱來命名。在這裏演示
* 我就用a,b,c,d的來命名吧,LKAProperty註解的groups就是用來設置
* 組名的,如下:
*/
@LKAModel
public class User {
@LKAProperty(value="用戶ID",hidden=true)//hidden設置成true,該不會在UI界面展示
private Integer id;
@LKAProperty(value="用戶名稱",testData="張三",groups= {"a"})
private String name;
@LKAProperty(value="年齡",required=false,groups= {"a"},testData="22")
private String age;
@LKAProperty(type=Role.class,value="角色對象")
private Role role;
@LKAProperty(value="用戶愛好",isArray=true,testData="運動")
private String[] likes;
@LKAProperty(type=Address.class,isArray=true,value="地址信息",groups= {"a"})
private List<Address> addresses;
.......get/set.......
}
@LKAModel
public class Address {
@LKAProperty(value="地址ID",testData="5")
private Integer id;
@LKAProperty(value="地址信息",testData="深圳市龍華區",groups= {"a"})
private String info;
.......get/set.......
}
/*
* 對象參數分組
* LKAGroup註解:用來指定對象的哪組參數來作爲入參,這裏指定了a組參數
*/
@LKAMethod(value="對象參數分組",contentType=ContentType.JSON,version="1.0")
@LKAResposes({
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"}),
@LKARespose(type=User.class,value= "用戶對象")
})
@PostMapping("getUser")
public Map<String,Object> getUser(@RequestBody @LKAGroup("a") User user) {
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","操作成功!");
map.put("user",user);
return map;
}
對象參數分組UI調試界面
響應參數的基本用法
@LKAMethod(value="響應參數基本用法")
@LKAParam(names= {"name","pwd"},values= {"用戶名","密碼"})
/*
* 以下兩種用法完全等價,帶s的複數屬性可以描述多個參數
* LKARespose註解:用來描述響應參數信息
* name:參數名稱(必填)
* value:參數作用(必填)
* description:參數的描述(選填)
* dataType:參數數據類型,默認String(選填)
* isArray:是否是集合或數組,默認false(選填)
*/
@LKARespose(names= {"code","msg"},values= {"狀態碼","響應消息"},descriptions= {"200-成功,其它-失敗","響應結果彈窗信息"})
/*@LKAResposes({
@LKARespose(name="code",value="狀態碼",description="200-成功,其它-失敗",dataType="String",
isArray=false),
@LKARespose(name="msg",value="響應消息")
})*/
@PostMapping("resTest")
public Map<String,Object> resTest(String name,String pwd) {
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","登錄成功,歡迎"+name+"光臨本系統");
return map;
}
響應參數的基本用法UI調試界面
響應參數複雜的Map結構用法
/*
* 響應參數複雜的Map結構用法
* type屬性:用來指定對象,如果該對象帶有@LKAModel註解和@LKAProperty會被自動掃描到
* parentName屬性:用來指定父級節點的屬性名,凡是parent開頭的都是父級節點屬性
* grandpaName屬性:用來指定爺級節點的屬性名,凡是grandpa開頭的都是爺級節點屬性
* 通過parent和grandPa開頭相關屬性用一條@LKARespose註解只能一次性描述1到3級節點,如果有5級或者10級節點該怎麼辦?
* 也有解決辦法,非常簡單,但註解可能會比較多,例如有這麼一個結構{a:{b:{c:{d:1}}}},我們可以這麼做:
* @LKARespose(name="a",value="一級"),
* @LKARespose(name="b",value="二級",parentName="a"),
* @LKARespose(name="c",value="三級",parentName="b"),
* @LKARespose(name="d",value="四級",parentName="c")
*/
@LKAMethod(value="響應參數複雜的Map結構用法")
@LKAResposes({
@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"}),
@LKARespose(name="total",value="總記錄數",parentName="result",parentValue="響應數據"),
@LKARespose(type=User.class,parentName="users",parentIsArray=true,parentValue="用戶對象列表",grandpaName="result"),
})
@PostMapping("getMap")
public Map<String,Object> getMap() {
Map<String,Object> map = new HashMap<>();
map.put("code",200);
map.put("msg","操作成功!");
Map<String,Object> data = new HashMap<>();
data.put("total",10);
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setName("張三");
User user2 = new User();
user2.setName("李四");
users.add(user1);
users.add(user2);
data.put("users",users);
map.put("result",data);
return map;
}
UI調試界面
響應參數複雜的對象結構用法
準備響應數據封裝對象
@LKAModel
public class ApiResult {
@LKAProperty(value="響應狀態",description="200-正常,其它-錯誤")
private String code;
@LKAProperty(value="響應消息")
private String msg;
@LKAProperty(value="響應數據")
private Map<String,Object> result = new HashMap<>();
private ApiResult() {}
public static ApiResult put(String key,Object value) {
ApiResult res = new ApiResult();
res.getResult().put(key, value);
return res;
}
..........get/set方法...........
}
演示接口
/*
* 響應參數複雜的對象結構用法
* 這個方法其實和上面的那個方法響應參數結構是一樣的,不一樣的地方是一個是Map,一個是ApiResut對象。
* 但是我們發現這個方法在響應參數描述是少用一個@LKARespose(names= {"code","msg"},values= {"狀態碼","消息"})註解,
* 這是因爲ApiResult對象已經通過@LKAProperty註解描述過"code","msg"屬性了,LKADocument會去自動掃描帶有@LKAModel註解的響應對象。
* 還有如果@LKARespose註解描述的參數和響應對象裏面的屬性有重複的話,@LKARespose註解描述的參數會覆蓋掉響應對象裏面的屬性
* group屬性:也可以實現響應參數分組,使用原理和請求參數分組是一樣的。
*/
@LKAMethod(value="響應參數複雜的對象結構用法")
@LKAResposes({
@LKARespose(name="total",value="總記錄數",parentName="result",parentValue="響應數據"),
@LKARespose(type=User.class,parentName="users",group="a",parentIsArray=true,parentValue="用戶對象列表",grandpaName="result"),
})
@PostMapping("getObj")
public ApiResult getObj() {
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setName("張三");
User user2 = new User();
user2.setName("李四");
users.add(user1);
users.add(user2);
return ApiResult.put("total",10).put("users",users);
}
UI調試界面
自定義接口或屬性標籤
教程我就寫到這裏了,基本上所有的功能都有講到,如果大家在使用過程中遇到什麼問題,可以留言或發郵件[email protected]給我,我會第一時間給大家解答。