驾一叶之扁舟 举匏樽以相属
寄蜉蝣于天地,渺沧海之一粟。哀吾生之须臾,羡长江之无穷。
挟飞仙以遨游,抱明月而长终。知不可乎骤得,托遗响于悲风。

从壹开始前后端分离 [.netCore 填坑 ] 三十四║Swagger:API多版本控制,带来的思考

前言

大家周二好呀,.net core + Vue 这一系列基本就到这里差不多了,今天我又把整个系列的文章下边的全部评论看了一下(我是不是很负责哈哈),提到的问题基本都解决了,还有一些问题,已经在QQ群里讨论过了,今天再写一篇,然后给这个系列画一个暂时的句号吧,这些天也考虑写点儿啥,希望看到的小伙伴给点儿意见哟,其实我也是能力有限,不敢保证精通,不过只要想学,基本都能学到点儿东西的,至少至少能给大家在繁忙或者无聊的开发生涯中,多一点儿学习的动力吧,至少群里边的小伙伴是这样(马上破百了,快来加入我们吧),目前写的都是浅显的,打算下一步向架构师微服务方向简单拓展下,这两天简单看了一下,真是云里来雾里去,不是很通俗,还得自己啃,一起加油吧!!!

1、什么是版本控制

这个词语大家已经不会陌生,平时开发的时候,一定会用到过 Git 、SVN 或者 VSS (这三个我都用过,Git 应该是最好的),这个就是源代码的版本控制。

来句官方定义:版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一。

那今天我们说的,就是 api接口的版本控制,这个大家一定也都接触到了,在我们使用的 swagger 中是这样的:

 

2、api版本控制的好处

简单来说,接口是APP的重要组成部分,数据是APP的核心,接口是连接APP和数据的纽带(这里的 APP 是广义上的接口调用者)。

一般情况下,我们项目中会有大量的接口,再加上版本的变化,接口的升级,一个接口,可能会有很多个稍有差异的接口,这个时候接口如果维护的不好,错一个就是一大片,那我们对 api 进行版本控制的好处有:

(1)有助于保护原有系统,不受影响,并及时修复问题
(2)可以实现用户的私人定制,(我之前接触过付费接口,可以这个意思)。
(3)快速迭代。

 

之前我在开发的时候,倒是没有考虑过这个问题,都是想当然的以为写代码只有一个版本,亦或者根本就没有版本概念,昨天晚上在看有一个小伙伴问到了 swagger 中,如何进行版本控制( 然后我想了想,在平时的开发中,我开发的项目中还没有遇到过版本控制,都是 web 项目+控制台项目,有问题就直接修改,有 bug 直接覆盖那种,从来没有考虑过版本,但是既然咱们这个系列是基于 api 接口的,版本应该是要有的,而且相信以后如果开发 api 项目的时候,也会遇到这个问题。我就研究了下 swagger 的源码,结合着网上的资料看了看,简单的配置了下,是这样的:

 

 

 

3、常见的版本控制有哪些?

通过上边的配置,我自认为很好的解决了这个问题,但是当我深入学习的时候,发现并不是,比如如何很好的调用不同版本的接口?,前端又如何对写好的接口地址进行快速修改?等等多个问题引起我的思考,通过搜索资料,我总结了以下,常见的版本控制有以下几个方案:

0、直接修改方法名,比如:/api/blog_v1,/api/blog_v2,/api/blog_v3... 虽然有时候也用,不过我直接 pass

1、通过路由控制,比如豆瓣:https://api.douban.com/v2/movie/in_theaters  //本文重点说明,个人推荐,其他的大家可以参考博友文章

2、通过参数选择,比如:http://localhost:58427/api/Values?api-version=2.0

3、通过http请求的 Headers 来控制,接口地址不变,下边会说到 

4、利用 content type 来控制 

 

老张:本文只是一个说明版本,并没有把所有的方案都 code 出来,重点说了下路由控制,剩下的只是引导大家去思考这个问题,然后继续学习,毕竟会一两个方法就行了,平时开发中,使用的并不是很频繁,有好的想法欢迎下边留言,或者来群里和我们的小伙伴热情互动吧!

 

一、在 swagger 中通过路由实现版本控制

1、注册多个版本api

1、在 Blog.Core 项目下新建 SwaggerHelper 文件夹,然后添加 CustomApiVersion.cs 用来控制版本

 

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 中,配置服务,遍历版本展示

在 ConfigureServices 方法内,修改 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 = "https://www.jianshu.com/u/94102b59cc2a" }
    });
});

 

 4、修改 SwagerUI 调用配置

在 Configure 方法内,修改 app.UseSwaggerUI 如下:

app.UseSwaggerUI(c =>
{
    //之前是写死的
    //c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
    //c.RoutePrefix = "";//路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件

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

 

5、查看效果

现在已经实现了,在 swagger 中,进行多版本的展示,那要如何进行控制呢,请往下看。

 

2、对接口进行版本配置

1、刚刚我们已经创建好了多版本的接口文档,那现在就需要配置接口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开发中,自带的一个组管理。

为什么要配置路径呢?是因为多版本的情况下,可能会出现重名函数,这里没有体现出来,因为使用的是 :V2_Blogtest ,下边的文章中会说到,如果一定要重名,需要怎么做。

 

2、这个时候查看效果,发现已经实现了我们文件开头的效果

 

 这个时候效果已经实现了,但是这么写显然不是很方便,首先,我们的组名 GroupName 是写死的 ”v2“,不利用拓展,然后呢,还需要再一次配置路由 Route,有小伙伴就发现了,既然这两个都是特性,有没有办法重写一个特性,把这两个合并呢,欸?!就是这样,请往下看。

 

3、自定义路由特性,实现路由+版本 双控制

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>
        /// 分组名称,是来实现接口 IApiDescriptionGroupNameProvider
        /// </summary>
        public string GroupName { get; set; }

        /// <summary>
        /// 自定义路由构造函数,继承基类路由
        /// </summary>
        /// <param name="actionName"></param>
        public CustomRouteAttribute(string actionName = "[action]") : base("/api/{version}/[controller]/" + actionName)
        {
        }
        /// <summary>
        /// 自定义版本+路由构造函数,继承基类路由
        /// </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 接口进行设置

 /// <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接口版本控制已经说完了,采用的方法是路由控制,我个人感觉还是挺好的,当然文章的开头也说到了,还是有其他的方法,这里就简单的其中一个,个人不是很推荐,但是大家可以看看。

二、同名接口的版本控制

在上边咱们说到了,如果两个版本的方法名一定要一直咋办呢,重载大家肯定都知道,但是同一个 controller 接口方法肯定无论参数还是名称全部都一样,就连返回类型也一样,所以不能重载,那我们应该怎么办呢?,请往下看。

 

1、 在 controller 文件夹下,新建两个文件夹, v1、v2

2、然后添加相同的接口控制器 ApbController.cs,自定义即可

 

3、在两个控制器中,添加相同的代码

 

这样就能实现同名方法的版本控制了。

 

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

这些方法我本打算写下来,发现不能通过 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

 

 

四、Github

https://github.com/anjoy8/Blog.Core

https://gitee.com/laozhangIsPhi/Blog.Core

posted @ 2018-10-16 13:52  老张的哲学  阅读(7936)  评论(31编辑  收藏
作者:老张的哲学
好好学习,天天向上
返回顶部小火箭
好友榜:
如果愿意,把你的博客地址放这里
jianshu.com/u/老张
SqlSugar codeisbug.com