ASP.NET CORE 第八篇 Swagger:API多版本控制,帶來的思考

原文作者:老張的哲學(xué)

1拯刁、什么是版本控制

這個詞語大家已經(jīng)不會陌生脊岳,平時開發(fā)的時候,一定會用到過 Git 垛玻、SVN 或者 VSS (這三個我都用過割捅,Git 應(yīng)該是最好的),這個就是源代碼的版本控制帚桩。

來句官方定義:版本控制是指對軟件開發(fā)過程中各種程序代碼亿驾、配置文件及說明文檔等文件變更的管理,是軟件配置管理的核心思想之一账嚎。

那今天我們說的莫瞬,就是 api接口的版本控制,這個大家一定也都接觸到了郭蕉,在我們使用的 swagger 中是這樣的:

image

2乏悄、api版本控制的好處

簡單來說,接口是APP的重要組成部分,數(shù)據(jù)是APP的核心恳不,接口是連接APP和數(shù)據(jù)的紐帶(這里的 APP 是廣義上的接口調(diào)用者)。

一般情況下开呐,我們項目中會有大量的接口烟勋,再加上版本的變化规求,接口的升級,一個接口卵惦,可能會有很多個稍有差異的接口阻肿,這個時候接口如果維護的不好,錯一個就是一大片沮尿,那我們對 api 進行版本控制的好處有:

(1)有助于保護原有系統(tǒng)丛塌,不受影響,并及時修復(fù)問題
(2)可以實現(xiàn)用戶的私人定制畜疾,(我之前接觸過付費接口赴邻,可以這個意思)。
(3)快速迭代啡捶。

之前我在開發(fā)的時候姥敛,倒是沒有考慮過這個問題,都是想當(dāng)然的以為寫代碼只有一個版本瞎暑,亦或者根本就沒有版本概念彤敛,昨天晚上在看有一個小伙伴問到了 swagger 中,如何進行版本控制( 然后我想了想了赌,在平時的開發(fā)中墨榄,我開發(fā)的項目中還沒有遇到過版本控制,都是 web 項目+控制臺項目勿她,有問題就直接修改袄秩,有 bug 直接覆蓋那種,從來沒有考慮過版本嫂拴,但是既然咱們這個系列是基于 api 接口的播揪,版本應(yīng)該是要有的,而且相信以后如果開發(fā) api 項目的時候筒狠,也會遇到這個問題猪狈。我就研究了下 swagger 的源碼,結(jié)合著網(wǎng)上的資料看了看辩恼,簡單的配置了下雇庙,是這樣的:

image

3、常見的版本控制有哪些灶伊?

通過上邊的配置疆前,我自認為很好的解決了這個問題,但是當(dāng)我深入學(xué)習(xí)的時候聘萨,發(fā)現(xiàn)并不是竹椒,比如如何很好的調(diào)用不同版本的接口?米辐,前端又如何對寫好的接口地址進行快速修改胸完?等等多個問題引起我的思考书释,通過搜索資料,我總結(jié)了以下赊窥,常見的版本控制有以下幾個方案:

0爆惧、直接修改方法名,比如:/api/blog_v1锨能,/api/blog_v2扯再,/api/blog_v3... 雖然有時候也用,不過我直接 pass

1址遇、通過路由控制熄阻,比如豆瓣:https://api.douban.com/v2/movie/in_theaters //本文重點說明,個人推薦傲隶,其他的大家可以參考博友文章
2饺律、通過參數(shù)選擇,比如:http://localhost:58427/api/Values?api-version=2.0
3跺株、通過http請求的 Headers 來控制复濒,接口地址不變,下邊會說到
4乒省、利用 content type 來控制

本文只是一個說明版本巧颈,并沒有把所有的方案都 code 出來,重點說了下路由控制袖扛,剩下的只是引導(dǎo)大家去思考這個問題砸泛,然后繼續(xù)學(xué)習(xí),畢竟會一兩個方法就行了蛆封,平時開發(fā)中唇礁,使用的并不是很頻繁,有好的想法歡迎下邊留言惨篱。

一盏筐、在 swagger 中通過路由實現(xiàn)版本控制

1、注冊多個版本api

1砸讳、在 Blog.Core 項目下新建 SwaggerHelper 文件夾琢融,然后添加 CustomApiVersion.cs 用來控制版本

image

2、在自定義API版本類中簿寂,添加枚舉版本號

    /// <summary>
    /// 自定義版本
    /// </summary>
    public class CustomApiVersion
    {
        /// <summary>
        /// Api接口版本 自定義
        /// </summary>
        public enum ApiVersions
        {
            /// <summary>
            /// v1 版本
            /// </summary>
            v1 = 1,
            /// <summary>
            /// v2 版本
            /// </summary>
            v2 = 2,
        }
    }

3漾抬、在項目啟動類 Startup.cs 中,配置服務(wù)常遂,遍歷版本展示
在 ConfigureServices 方法內(nèi)纳令,修改 services.AddSwaggerGen 中的 c.SwaggerDoc 文檔如下:

//遍歷出全部的版本,做文檔信息展示
typeof(ApiVersions).GetEnumNames().ToList().ForEach(version =>
{
    c.SwaggerDoc(version, new Info
    {
        // {ApiName} 定義成全局變量,方便修改
        Version = version,
        Title = $"{ApiName} 接口文檔",
        Description = $"{ApiName} HTTP API " + version,
        TermsOfService = "None",
        Contact = new Contact { Name = "Blog.Core", Email = "Blog.Core@xxx.com", Url = "http://www.reibang.com/u/94102b59cc2a" }
    });
});

4平绩、修改 SwagerUI 調(diào)用配置
在 Configure 方法內(nèi)坤按,修改 app.UseSwaggerUI 如下:

app.UseSwaggerUI(c =>
{
    //之前是寫死的
    //c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
    //c.RoutePrefix = "";//路徑配置,設(shè)置為空馒过,表示直接在根域名(localhost:8001)訪問該文件

    //根據(jù)版本名稱倒序 遍歷展示
    typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
    {
        c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
    });
});

5、查看效果


image

現(xiàn)在已經(jīng)實現(xiàn)了酗钞,在 swagger 中腹忽,進行多版本的展示,那要如何進行控制呢砚作,請往下看窘奏。

2、對接口進行版本配置

1葫录、剛剛我們已經(jīng)創(chuàng)建好了多版本的接口文檔着裹,那現(xiàn)在就需要配置接口api了
在 BlogController.cs 中新建一個 V2_Blogtest() 方法:

/// <summary>
   /// 獲取博客測試信息 v2版本
   /// </summary>
   /// <returns></returns>
   [HttpGet]
   //MVC自帶特性 對 api 進行組管理
   [ApiExplorerSettings(GroupName = "v2")]
   //路徑 如果以 / 開頭,表示絕對路徑米同,反之相對 controller 的想u地路徑
   [Route("/api/v2/blog/Blogtest")]
   public async Task<object> V2_Blogtest()
   {
       return Ok(new { status = 220, data = "我是第二版的博客信息" });

   }

這里用到了 ApiExplorerSettings 特性骇扇,在mvc開發(fā)中,自帶的一個組管理面粮。

為什么要配置路徑呢少孝?是因為多版本的情況下,可能會出現(xiàn)重名函數(shù)熬苍,這里沒有體現(xiàn)出來稍走,因為使用的是 :V2_Blogtest ,下邊的文章中會說到柴底,如果一定要重名婿脸,需要怎么做。

2柄驻、這個時候查看效果狐树,發(fā)現(xiàn)已經(jīng)實現(xiàn)了我們文件開頭的效果

image

這個時候效果已經(jīng)實現(xiàn)了,但是這么寫顯然不是很方便凿歼,首先褪迟,我們的組名 GroupName 是寫死的 ”v2“,不利用拓展答憔,然后呢味赃,還需要再一次配置路由 Route,有小伙伴就發(fā)現(xiàn)了虐拓,既然這兩個都是特性心俗,有沒有辦法重寫一個特性,把這兩個合并呢,欸城榛?揪利!就是這樣,請往下看狠持。

3疟位、自定義路由特性,實現(xiàn)路由+版本 雙控制

1喘垂、在根目錄的 SwaggerHelper 文件夾下甜刻,新建一個 CustomRouteAttribute.cs

/// <summary>
    /// 自定義路由 /api/{version}/[controler]/[action]
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class CustomRouteAttribute : RouteAttribute, IApiDescriptionGroupNameProvider
    {

        /// <summary>
        /// 分組名稱,是來實現(xiàn)接口 IApiDescriptionGroupNameProvider
        /// </summary>
        public string GroupName { get; set; }

        /// <summary>
        /// 自定義路由構(gòu)造函數(shù),繼承基類路由
        /// </summary>
        /// <param name="actionName"></param>
        public CustomRouteAttribute(string actionName = "[action]") : base("/api/{version}/[controller]/" + actionName)
        {
        }
        /// <summary>
        /// 自定義版本+路由構(gòu)造函數(shù)正勒,繼承基類路由
        /// </summary>
        /// <param name="actionName"></param>
        /// <param name="version"></param>
        public CustomRouteAttribute(ApiVersions version, string actionName = "[action]") : base($"/api/{version.ToString()}/[controller]/{actionName}")
        {
            GroupName = version.ToString();
        }
    }

2得院、對 api 接口進行設(shè)置

/// <summary>
 /// 獲取博客測試信息 v2版本
 /// </summary>
 /// <returns></returns>
 [HttpGet]
 ////MVC自帶特性 對 api 進行組管理
 //[ApiExplorerSettings(GroupName = "v2")]
 ////路徑 如果以 / 開頭,表示絕對路徑章贞,反之相對 controller 的想u地路徑
 //[Route("/api/v2/blog/Blogtest")]

 //和上邊的版本控制以及路由地址都是一樣的
 [CustomRoute(ApiVersions.v2, "Blogtest")]
 public async Task<object> V2_Blogtest()
 {
     return Ok(new { status = 220, data = "我是第二版的博客信息" });

 }

瀏覽效果都是一樣的祥绞,這里就不展示了,從這里看出來鸭限,還是很方便的蜕径。

說到這里,基于 swagger 的api接口版本控制已經(jīng)說完了里覆,采用的方法是路由控制丧荐,我個人感覺還是挺好的,當(dāng)然文章的開頭也說到了喧枷,還是有其他的方法虹统,這里就簡單的其中一個,個人不是很推薦隧甚,但是大家可以看看车荔。

二、同名接口的版本控制

在上邊咱們說到了戚扳,如果兩個版本的方法名一定要一直咋辦呢忧便,重載大家肯定都知道,但是同一個 controller 接口方法肯定無論參數(shù)還是名稱全部都一樣帽借,就連返回類型也一樣珠增,所以不能重載,那我們應(yīng)該怎么辦呢砍艾?蒂教,請往下看。

1脆荷、 在 controller 文件夾下凝垛,新建兩個文件夾懊悯, v1、v2

2梦皮、然后添加相同的接口控制器 ApbController.cs炭分,自定義即可

image

3、在兩個控制器中剑肯,添加相同的代碼

image

這樣就能實現(xiàn)同名方法的版本控制了捧毛。

三、其他不適用于 swagger 的接口版本控制方法

這些方法我本打算寫下來让网,發(fā)現(xiàn)不能通過 swagger 展示岖妄,會報錯,只能通過 postman 測試寂祥,所以對我來說不是很完美,這里把博友的文章貼出來七兜,大家可以自己看一下丸凭。

ASP.Net Core WebApi幾種版本控制對比
ASP.NET Core API 版本控制
Your API versioning is wrong, which is why I decided to do it 3 different wrong ways

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市腕铸,隨后出現(xiàn)的幾起案子惜犀,更是在濱河造成了極大的恐慌,老刑警劉巖狠裹,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虽界,死亡現(xiàn)場離奇詭異,居然都是意外死亡涛菠,警方通過查閱死者的電腦和手機莉御,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俗冻,“玉大人礁叔,你說我怎么就攤上這事∑。” “怎么了琅关?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長讥蔽。 經(jīng)常有香客問我涣易,道長,這世上最難降的妖魔是什么冶伞? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任新症,我火速辦了婚禮,結(jié)果婚禮上碰缔,老公的妹妹穿的比我還像新娘账劲。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布瀑焦。 她就那樣靜靜地躺著腌且,像睡著了一般。 火紅的嫁衣襯著肌膚如雪榛瓮。 梳的紋絲不亂的頭發(fā)上铺董,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音禀晓,去河邊找鬼精续。 笑死,一個胖子當(dāng)著我的面吹牛粹懒,可吹牛的內(nèi)容都是我干的重付。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼凫乖,長吁一口氣:“原來是場噩夢啊……” “哼确垫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起帽芽,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤删掀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后导街,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體披泪,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年搬瑰,在試婚紗的時候發(fā)現(xiàn)自己被綠了款票。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡泽论,死狀恐怖徽职,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情佩厚,我是刑警寧澤姆钉,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站抄瓦,受9級特大地震影響潮瓶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钙姊,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一毯辅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧煞额,春花似錦思恐、人聲如沸沾谜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽基跑。三九已至,卻和暖如春描焰,著一層夾襖步出監(jiān)牢的瞬間媳否,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工荆秦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留篱竭,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓步绸,卻偏偏與公主長得像掺逼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瓤介,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容