Swagger / Open API 在Restful API 領域已慢慢成爲標準,愈來愈多的系統使用swagger來規範開發接口文檔,因爲Swagger 自己並不依賴特定的語言和開發平臺,因此特別合適做爲先後端分離的接口標準來使用。 Swagger 官方提供了兩種文檔UI形式,一種是 Swagger UI, 另外一種是 Swagger Editor.node
Swagger UI 經常做爲項目工程的一部份,不少程序都採用自身的特性,在程序代碼上增長註釋、註解、裝飾器等方式完成swagger 的接口文檔自動生成和文檔展現。ios
Swagger Editor 提供了一個在線編輯的編輯器,使之能以文檔的方式編輯接口,並提供了兩塊的生成功能:服務端代碼與客戶端代碼,代碼生成涵蓋了大部分的主流語言與框架很是方便。git
不少同窗可能有疑問,這樣生成的代碼到底能用嗎?github
個人回答不只是能用,並且很好用。 以 ng-alain 爲例typescript
代碼位置 github.com/vellengs/ty… 定製下provider 的 basePath 設置。json
export function apiConfig(): Configuration {
return new Configuration({
basePath: `${location.protocol}//${location.host}`
});
}
複製代碼
註冊下模塊axios
ApiModule.forRoot(apiConfig),
複製代碼
而後把目錄釋放到 github.com/vellengs/ty… 這個目錄,看清楚,generted目錄 是能夠一字不改的,若是改了之後須要從新生成豈不是大麻煩?後端
放置到 angular 項目裏後就能夠愉快的使用 service了,以下示例: github.com/vellengs/ty…api
profileSave(event?) {
const entry: EditProfileDto = Object.assign({}, event);
this.coreService.userUpdate(entry).subscribe((res) => {
if (res) {
this.settings.setUser(res);
this.msg.success('我的資料修改爲功');
}
});
}
saveSysSettings(event) {
const entry = Object.assign({}, event);
this.coreService.settingUpdateSettingsByName('main', entry).subscribe((res) => {
if (res) {
this.settingsData = res;
this.msg.success('系統設置更新成功');
}
});
}
load() {
this.coreService.settingGetSettingsByName('main').subscribe((res) => {
if (res) {
this.settingsData = res;
}
});
}
複製代碼
方法變得能夠感知了。bash
上一步驟已經能夠使用了,可是有點小小的麻煩;每次都要打開 editor.swagger.io 粘貼文檔上去,而後去點生成,而後解壓,這樣是否是不夠平滑呢?
那讓咱們寫個腳本吧,自動完成上面的事情。 完整腳本地址
async function loadSwagger() {
/** 讀取 swagger.json 接口文檔文件 */
const jsonPath = path.resolve(process.cwd(), 'dist', 'swagger.json');
const json = require(jsonPath);
const client = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});
/**
* 提交 post 到服務器並得到下載連接
*/
const result = await client.post(gateway, { spec: json });
if (result.data && result.data.link) {
const response = await client({
method: 'GET',
url: result.data.link,
responseType: 'stream'
})
const local = path.resolve(process.cwd(), 'swagger.zip');
const generatedFolder = path.resolve(process.cwd(), './../client/src/generated');
const templateFolder = path.resolve(process.cwd(), 'decompress', 'typescript-angular-client');
const decompress = path.resolve(process.cwd(), 'decompress');
// 處理下載壓縮包文件,解壓並刪除臨時文件
response.data.pipe(fs.createWriteStream(local)).on('finish', (done: any) => {
fs.createReadStream(local).pipe(unzip.Extract({ path: 'decompress' })).on('close',
async (done: any) => {
fs.unlinkSync(local);
await removeFolder(generatedFolder);
fs.renameSync(templateFolder, generatedFolder);
await removeFolder(decompress);
});
});
}
}
/**
* 若已經生成,則刪除文件夾
* @param folder 文件夾
*/
async function removeFolder(folder: string) {
if (fs.existsSync(folder)) {
await new Promise((resolve) => {
rimraf(folder, () => {
resolve(true);
});
})
}
}
loadSwagger();
複製代碼
總共沒幾行代碼,是否是以爲很簡單呢,沒錯要的就是簡單,可是很好的完成了咱們的工做。
有了腳本以後你只要
ts-node xxxxx/apigen.ts
複製代碼
便可完成工做。
結束語,標準的接口在先後端分離的開發中起到很好的規範做用,而平滑的開發體驗也是重要的一環,若是你有疑問,或者有更好的方式,歡迎和做者交流學習 github.com/vellengs