• 从壹开始前后端分离 [.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

  • 相关阅读:
    sql执行顺序图
    solor5.4学习笔记
    linux 安装
    falsh,.swf文件修改z-index
    mysql 分区
    再次构架心得
    服务器,数据库连接注意mysql的user表
    数据库操作
    一知半见的load与get
    处理中文空格.replace((char)12288,' ')
  • 原文地址:https://www.cnblogs.com/laozhang-is-phi/p/9795689.html
Copyright © 2020-2023  润新知