我们在进行webapi服务开发时,会遇到一些多个版本的api共存的情况发生,例如某一版本APP上线后,需求发生变更,需要在下一个升级版本更新API,但同时又需要保证这个APP版本能正常使用,这时候就需要采用API服务版本控制。

版本控制一般有以下几种方式:

  1. 在url上增加查询字符串参数的方式,追加版本,例如 api/service?v=2
  2. 在url路径上增加版本。例如:api/v2/service(这种方式个人认为目前是最优雅的方式)
  3. 在http请求head中加入版本标识

目前微软提供了 Microsoft.AspNetCore.Mvc.Versioning 组件,能够支持以上几种方式。

组件注册

            services.AddApiVersioning(options =>
            {
                options.ReportApiVersions = true;
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
            });
  • ReportAPIVersions: 这是可选的。但是, 当设置为 true 时, API 将返回响应标头中支持的版本信息。
  • AssumeDefaultVersionWhenUnspecified: 此选项将用于不提供版本的请求。默认情况下, 假定的 API 版本为1.0。(这个经测试对url追加版本方式不起作用)
  • DefaultApiVersion: 此选项用于指定在请求中未指定版本时要使用的默认 API 版本。这将默认版本为1.0。

几个重要的类

  • ApiVersion 特性标识当前Controller的版本,注意路由的配置。这里我们采用了第 2 个版本控制方式
  • MapToApiVersion 属性允许将单个 API 操作映射到某一版本

实现一个小需求:在同一个Controller里面新增一个api版本

  http://localhost:5000/gateway/api/user/headclaims           --->指向 默认v1版本

  http://localhost:5000/gateway/api/v1/user/headclaims      ---->指向 v1版本

  http://localhost:5000/gateway/api/v2/user/headclaims      ---->指向 v2版本

配置如下:

    [ApiVersion("1.0")]
    [ApiVersion("2.0")]
    //多路由支持
    [Route("api/v{version:apiVersion}/[controller]")]
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private readonly IUserAppService _userService;
        public UserController(IUserAppService userService)
        {
            _userService = userService;
        }
 
        [Route("headclaims")]
        [HttpGet]
        public IActionResult HeadClaims()
        {
            var claimTypes = new List<string> { "name", "phone", "userId", "introduce" };
            var claimHeads = Request.Headers.Where(x => claimTypes.Contains(x.Key));
            var user = Request.HttpContext.User;
            if (claimHeads == null) return Ok();
            var returnObj = new JObject();
            foreach (var ch in claimHeads)
            {
                returnObj.Add(ch.Key, ch.Value.ToString());
            }
            return Ok(returnObj);
        }
        [Route("headclaims")]
        [HttpGet, MapToApiVersion("2.0")]
        public IActionResult HeadClaimsv2()
        {
            var claimTypes = new List<string> { "name", "phone" };
            var claimHeads = Request.Headers.Where(x => claimTypes.Contains(x.Key));
            var user = Request.HttpContext.User;
            if (claimHeads == null) return Ok();
            var returnObj = new JObject();
            foreach (var ch in claimHeads)
            {
                returnObj.Add(ch.Key, ch.Value.ToString());
            }
            return Ok(returnObj);
        }
    }

 

posted on 2020-03-13 14:10  gt1987  阅读(564)  评论(0编辑  收藏  举报