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

原文作者:老张的哲学

1、什么是版本控制

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

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

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

image

2、api版本控制的好处

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

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

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

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

image

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 用来控制版本

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 中,配置服务,遍历版本展示
在 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、查看效果

 

image

现在已经实现了,在 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、这个时候查看效果,发现已经实现了我们文件开头的效果

image

这个时候效果已经实现了,但是这么写显然不是很方便,首先,我们的组名 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,自定义即可

image

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

image

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

三、其他不适用于 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

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值