API 文檔是前後端對接的基本,但如果還停留在手寫文檔的階段,那就真的太 out 了。大家可能也嘗試過各種 API 接口管理的工具,比如 postman 、apizza 等,但個人使用下來還是感覺麻煩了,長期來看我是拒絕的。
從目前 API 文檔生成及管理上來看,Swagger 可算是不錯的框架。今天來介紹一下 Swagger 的使用,以下使用 .NETCore Web API 爲例,其他語言也類似,最終都是依賴生成的 json/yaml 文件。
文檔生成
內嵌代碼方式
新建 ASP.NET Core Web 應用程序,選擇 API 類型
-
Nuget 安裝 Swashbuckle.AspNetCore
Install-Package Swashbuckle.AspNetCore
-
在 Startup.cs 中的 ConfigureServices 和 Configure 方法添加 Swagger 相關代碼
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); // swagger.json 文檔生成參數配置 services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new Info { Title = "SwaggerTest接口文檔", Version = "1.0.0" }); options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "SwaggerTest.XML")); }); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); app.UseSwagger(); // 通過SwaggerUI展示 app.UseSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerTest"); }); }
-
項目屬性中的 ”生成“ 勾選 “XML 文檔文件” (Debug 和 Release 兩種模式下都勾選上)。這一步的目的是將代碼註釋生成文檔,所以接口方法及參數都務必加上完整的註釋
-
運行項目,訪問 http://localhost:62654/swagger/index.html
以上方式使用起來非常簡單,但個人覺得存在以下問題:
Startup 中需要加入 Swagger 相關的一些代碼,不夠整潔
如果有多個 API 服務,每個服務都需要添加類似代碼,而且每個服務的文檔地址獨立,不能統一管理
非內嵌代碼方式
Swagger UI 本身是一個可以單獨使用的前端項目。從 UseSwaggerUI 的參數配置來看:
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerTest");
});
其實只要將 "/swagger/v1/swagger.json" 這個文件引用進去即可,所以只需存在一種可以根據項目的 dll 文件生成 swagger.json 的方式,然後把生成的 swagger.json 引用到 Swagger UI 。NSwag 恰好可以滿足這個需求。
拋開內嵌代碼的方式,假設現在是一個全新的 Web API 項目。
下載 NSwag ,在 Downloads 中下載 NSwag command line tools。如下載後解壓地址爲: C:\Users\Administrator\Downloads\NSwag\
-
在項目根目錄下新建 bat 文件並添加腳本,執行生成 swagger.json (windows 環境)
:: 生成的文檔名,每個項目最好是唯一的 SET FILE_NAME=swaggerTest :: 項目dll地址 SET SOURCE_DLL=bin\Release\netcoreapp2.1\publish\SwaggerTest.dll :: 文檔生成的目標文件夾 SET TARGET_DIR=D:\ApiDoc\public\docs\ :: Swagger文檔配置 :: 標題 SET TITLE=SwaggerTest接口文檔 :: 描述 SET DESCRIPTION=SwaggerTest接口文檔描述 :: 版本 SET VERSION=1.0.0 :: 接口測試請求的host地址,不同的api服務有不同的host SET HOST=localhost:5000 :: 通過 dotnet-nswag 執行生成命令 dotnet C:\Users\Administrator\Downloads\NSwag\NetCore21\dotnet-nswag.dll webapi2swagger /assembly:"%SOURCE_DLL%" /AspNetCore:true /output:%TARGET_DIR%%FILE_NAME%.json /InfoTitle:"%TITLE%" /InfoDescription:"%DESCRIPTION%" /InfoVersion:%VERSION% /ServiceHost:%HOST%
bat 腳本執行完成後,在 D:\ApiDoc\public\docs\ 目錄下就會多出一個 swaggerTest.json,以這種方式我們並不需要修改任何代碼。到目前爲止,API 文檔對應的 json 文件就有了,接下來就是把它通過 Swagger UI 展示出來。假設每個 API 項目都生成一個 json 文件到指定的目錄,而 Swagger UI 本身支持配置多個文檔 url 地址,這就意味着可以搭建出了一個 API 文檔管理平臺。
文檔管理
下載 Swagger UI 並解壓
-
搭建一個 Node.js 項目,可使用 Express 或者 Koa 框架(其他語言的項目也可以,任意選擇)
將 swagger-ui dist 文件夾下的文件全部複製到項目的 public 文件夾下
安裝 express
-
新建 index.js,添加如下代碼
const express = require('express'); const app = express(); app.use('/', express.static('public')); app.listen(3000, function () { console.log('app listening on http://localhost:3000'); });
-
啓動服務
node index.js
完成以上步驟,Swagger UI 的站點就搭建完成了,訪問 http://localhost:3000 會出現一個默認的 API 接口文檔頁面。
打開 public/index.html 會發現有這麼一段代碼:
const ui = SwaggerUIBundle({
url: "https://petstore.swagger.io/v2/swagger.json",
...
})
這裏的 url 配置了一個默認的 swagger.json文件的地址,所以我們只需要把 url 替換成上面生成的 swaggerTest.json 地址就可以了,將 swaggerTest.json 複製到 public/docs 目錄下
const ui = SwaggerUIBundle({
url: "./docs/swaggerTest.json",
...
})
如果有多個 json 文件就不能使用 url 參數,需要修改成 urls 參數,具體可參考 Swagger UI 參數配置,爲了不需要每次手動調整 urls,所以需要動態讀取 docs 文件夾下的文件,生成的文檔只需要傳到這個目錄下就可以直接查看和測試。
在 index.js 增加一個接口:
app.get('/getDocs', function (req, res) {
let docFileInfos = [];
let pathDir = __dirname + '/public/docs';
try {
let fileNames = fs.readdirSync(pathDir);
fileNames.forEach(function (fileName) {
let data = fs.readFileSync(pathDir + '/' + fileName, 'utf8');
data = data.trim();
let json = JSON.parse(data);
docFileInfos.push({
url: './docs/' + fileName,
name: json.info.title
});
});
} catch (err) {
console.log(err);
}
res.send(docFileInfos);
});
public/index.html 引入 axios,並調用 getDocs 接口獲取結果,將 response.data 賦給 SwaggerUIBundle 的 urls 參數。
axios.get('/getDocs')
.then(function (response) {
if (response.status === 200 && response.data.length) {
...
}
});
當存在多個 json 文件的時候,可以從下拉選項中進去切換