這算是在博客園的第一篇博客吧,以後發的應該也會同步到博客園上。前端
此前的博客地址: https://blog.mytyiluo.cnnode
Swagger是一個開源軟件框架,可幫助開發人員設計,構建,記錄和使用RESTful Web服務。ios
其中,Swagger能夠生成一個交互式的API控制檯,以便於快速測試API。git
從我的角度講,Swagger對於先後端分離的小團隊來講是很是有幫助的。尤爲是像咱們這種平時沒寫文檔習慣的人來講,Swagger能根據代碼自動生成文檔可謂是一大福音,不再用被人追着問這API究竟是怎麼用的。github
這裏,我將會具體說下最近我使用Swagger的一些心得和體會,團隊的開發環境以下:json
對於ASP.NET Core來講,生成文檔這一步仍是相對容易的,且對代碼基本沒有侵入性。只需在Startup中配置一下便可,大體步驟基本以下:axios
這裏,我所使用的是Swashbuckle.AspNetCore,直接用VS的NuGet包管理器下載便可。小程序
而後在ConfigureServices
中配置以下:後端
services.AddSwaggerGen(c => { // 定義文檔 c.SwaggerDoc("v1", new Info { Title = "Qincai API", Version = "v1" }); });
並在Configure
中啓用該Services:微信小程序
// 使用Swagger app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Qincai API v1"); });
隨後運行,打開瀏覽器host/swagger
便可看到所生成的API文檔。
若還有不清楚的,能夠參考微軟官方的文檔。
完成到這裏,是否是發現你和圖中生成的樣子有點不太同樣,好比說,爲何沒有註釋,以及認證用的小鎖,那這裏咱們就須要進一步配置。
若是你們有在VS中寫C#經歷的話,確定會對XML註釋影響深入,經過簡單的///
就能夠自動生成規範的註釋格式。那這裏,咱們的Swagger也正是利用了這些XML註釋來標記對應的API。
首先,咱們須要啓用VS中導出XML文檔的功能,在項目屬性中,生成 > 輸出,勾選XML文檔文件,並填寫對應的路徑,我所寫的是項目根目錄。
而後再到以前的ConfigureServices
中添加以下:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "Qincai API", Version = "v1" }); // file 是你在項目屬性中配置的相對路徑 var filePath = System.IO.Path.Combine(AppContext.BaseDirectory, file); c.IncludeXmlComments(filePath); });
從新生成,再運行,你能夠看到Swagger中就對API以及參數添加上了註釋。
在實際開發中,咱們經常是須要給咱們的API添加上認證功能以免非法的訪問,所以咱們也就須要給Swagger中的API標識上是否須要認證,而且添加提供Token的功能,以方便在Swagger的控制檯中調試。
簡單來講,仍是在ConfigureServies
中,配置以下:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "Qincai API", Version = "v1" }); var filePath = System.IO.Path.Combine(AppContext.BaseDirectory, file); c.IncludeXmlComments(filePath); // 定義認證方式 c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "請鍵入JWT Token,格式爲'Bearer '+你的Token。", Name = "Authorization", Type = "apiKey" }); // 網上爲全局API添加認證參數的方法 // c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> { // { "Bearer", Enumerable.Empty<string>() }, // }); // 在過濾器中爲須要認證的API添加對應參數 // 過濾器的定義見下文 c.OperationFilter<AuthorizationHeaderOperationFilter>(); });
這裏值得說一下的是,網上廣泛都是全局添加認證參數,致使一些不須要認證的API也被打上了標識,這在Swagger 控制檯中影響倒不大,但在後續的導出API時就麻煩了,全部在這裏,我使用自定義過濾器的方式來只爲須要認證的API添加認證參數。
根據上文,咱們先定義一個AuthorizationHeaderOperationFilter
類,它須要實現IOperationFilter
接口,類定義以下:
/// <summary> /// 判斷是否須要添加Authorize Header /// </summary> public class AuthorizationHeaderOperationFilter : IOperationFilter { /// <summary> /// 爲須要認證的Operation添加認證參數 /// </summary> /// <param name="operation">The Swashbuckle operation.</param> /// <param name="context">The Swashbuckle operation filter context.</param> public void Apply(Operation operation, OperationFilterContext context) { // 獲取對應方法的過濾器描述 // 應該也就是所添加的Attribute var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors; // 判斷是否添加了AuthorizeFilter // 也就是[Authorize] var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter); // 判斷是否添加了IAllowAnonymousFilter // 也就是[AllowAnonymous] var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter); // 僅當須要認證且不是AllowAnonymous的狀況下,添加認證參數 if (isAuthorized && !allowAnonymous) { // 若該Operation不存在認證參數的話, // 這個Security將是null,而不是空的List if (operation.Security == null) operation.Security = new List<IDictionary<string, IEnumerable<string>>>(); // 添加認證參數 operation.Security.Add(new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } } }); } } }
從新生成後運行,應該就能夠看到須要認證的API都帶上了一把小鎖。
雖然說配置並不算難,但仍是須要注意一些地方。
注意寫好XML註釋
以前也說了,Swagger的註釋是根據XML文檔生成的,反過來講,若是你沒寫XML註釋,Swagger上也就是不會有註釋的。
另外,在你啓用XML文檔輸出以後,VS也會很貼心的爲你把沒有寫XML註釋的地方都標爲Warning。╮(╯▽╰)╭,因此安心的把註釋都補一遍吧。
爲參數添加數據註解
Swagger是支持部分數據註解的,好比[Required]
之類的。
結合[ApiController]
自帶的模型驗證功能,豈不美哉。
將XML文檔複製到輸出目錄
若你在發佈應用後發現XML不見了,那可能就是你沒有爲XML文檔文件配置複製到輸出目錄的屬性。
打開資源管理器,右鍵對應的文件,咱們在屬性中能夠看到有複製到輸出目錄的屬性,將其設置爲始終複製就Ok。
以上就是我最近所用到的Swagger的一些功能。
在一開始也說了,使用Swagger的主要目的就是方便小團隊的溝通,但事實上,由於咱們前端的人少(你們都是CSS鬼才),致使咱們開發新API的速度每每比前端進度快,沒幾天前端那邊就須要更新一下API的庫(將小程序的CallBack封裝成Promise)。
所以,就有了根據Swagger自動生成Js可用的API文件的想法,其實想法的自己是來自於Abp項目的設計(真的很優秀),但出於一些方面的考慮,咱們姑且還沒采用Abp。
隨後,就是查找資料了,確實Swagger有這方面的支持,其中官方關於Js的庫是徹底動態的,但惋惜不適用於小程序。而後,就發現了第三方的swagger-js-codegen,可用於生成靜態的Js代碼,且提供了自定義模板的功能。網上也很多基於這個庫的其餘模板,好比說axios
之類的,但沒有適用於微信小程序的,不過問題不大,模板是基於mustache
的,動手擼就是了。
模板代碼有點長就不在這裏放出了,你們還請移步GitHub。
這裏我就簡單說下大體思路,
模板自己是基於原來的nodejs模板改的,咱們所需作的就是將http請求部分的代碼改成使用wx.request
,以下簡單的封裝便可:
/** * HTTP Request * @method * @name {{&className}}#request * @param {string} method - HTTP 請求方法 * @param {string} url - 開發者服務器接口地址 * @param {object} data - 請求的參數 * @param {object} headers - 設置請求的 header ,默認爲 application/json */ request(method, url, parameters, data, headers){ return new Promise((resolve, reject) => { wx.request({ url: url, data: data, header: headers, method: method, success: res => { if(res.statusCode >= 200 && res.statusCode <= 299) { resolve(res.data) } else { reject(res) } }, fail: e => reject(e) }) }) }
對應method的話,基本沒怎麼改,只根據微信小程序全部參數都是傳遞給data,作了點簡化。
對於認證部分,根據咱們本身的需求,換成了這樣的實現:
new Promise((resolve, reject) => { this.authenticate() .then(token => { headers['Authorization'] = 'Bearer ' + token; resolve(this.request('{{method}}', domain + path, parameters, data, headers)) }) })
其中this.authenticate
是由外部傳入的function
,返回一個包含Token
的Promise
。
導出後,在小程序中的使用就相似於:
import API from './api.js' api = new API('http://localhost:5000') api.setAuthenticate(function () { return new Promise((resolve, reject) => { // 你的認證邏輯 resolve(token) }) })
而後,就能夠開心地調用各類方法了。
最後,再放一遍Demo的連接:https://github.com/yiluomyt/swagger-wxopen-codegen-template,發現有問題歡迎提Issue。