什么是 API 的多版本问题?Android 等 App 存在着多版本客户端共存的问题:App 最新版已经升级到了 5.0 了,但是有的用户手机上还运行着 4.8、3.9 甚至 2.2 版本的 App,由于早期没有内置升级机制、用户不会升级、用户拒绝升级等原因,造成这些旧版本 App 也在运行。开发新版本 App 的时候,,要给接口增加新的成果或者改削以前接口的规范,会造成旧版本 App 无法使用,因此在必然情况下会“保存旧接口的运行、新成果用新接口”,这样就会存在多版本接口共存的问题。
凡是的做法是:旧版接口做一个代码分支,除了进行 bug 改削外,旧版本接口不再做窜改;新接口代码继续演化升级。在客户端请求的时候带着要请求的接口版本号,在处事器端选择合适的版本代码进行措置惩罚惩罚。
技术措置惩罚惩罚要领:
1、 (最保举)差别版本用差此外域名:v1.api.rsfy.com、v2.api.rsfy.com、v3……;
2、 在 url、报文头等中带差此外版本信息,用 Nginx 等做反向代办代理处事器,然后将 到差此外处事器措置惩罚惩罚。
3、 多个版本的 Controller 共处在一个项目中,然后使用 [RoutePrefix] 或者
IHttpControllerSelector 按照报文头、路径等选择差此外 Controller 执行。下面主要讲这要领
(保举):自界说 IHttpControllerSelector
改削默认路由,如果还想用{controller}/{action}的方法,那么改就是了
此中v1,v2代表这版本号,差别版本的 Controller 放到差此外 namespace 下
config.Routes.MapHttpRoute( name: "DefaultApiv1", routeTemplate: "api/v1/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional }); config.Routes.MapHttpRoute( name: "DefaultApiv2", routeTemplate: "api/v2/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
首先自界说类VersionControllerSelector担任DefaultHttpControllerSelector
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text.RegularExpressions; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; namespace ApiDemo { public class VersionControllerSelector:DefaultHttpControllerSelector { private readonly HttpConfiguration _config; public VersionControllerSelector(HttpConfiguration config) : base(config) { _config = config; } public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping() { Dictionary<string, HttpControllerDescriptor> dict = new Dictionary<string, HttpControllerDescriptor>(); foreach (var asm in _config.Services.GetAssembliesResolver().GetAssemblies()) { //获取所有担任自ApiController的非抽象类 var controllerTypes = asm.GetTypes() .Where(t => !t.IsAbstract && typeof(ApiController) .IsAssignableFrom(t)).ToArray(); foreach (var ctrlType in controllerTypes) { //从namespace中提取出版本号 定名空间,有可能不是当前的weiapi项目 var match = Regex.Match(ctrlType.Namespace, GetType().Namespace + @".Controllers.v(\d+)"); if (match.Success) { string verNum = match.Groups[1].Value;//获取版本号 //从PersonController中拿到Person string ctrlName = Regex.Match(ctrlType.Name, "(.+)Controller").Groups[1].Value; //Personv2为key string key = ctrlName + "v" + verNum; dict[key] = new HttpControllerDescriptor(_config, ctrlName, ctrlType); } } } return dict; } //设计就是返回HttpControllerDesriptor的过程 public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { //获取所有的controller键值调集 var controllers = GetControllerMapping(); //获取路由数据 var routeData = request.GetRouteData(); //从路由中获取当前controller的名称 var controllerName = (string)routeData.Values["controller"]; var verNum = request.Headers.TryGetValues("ApiVersion", out var versions) ? versions.Single() : Regex.Match(request.RequestUri.PathAndQuery, @"api/v(\d+)").Groups[1].Value; //获取版本号 var key = controllerName + "v" + verNum;//获取Personv2 return controllers.ContainsKey(key) ? controllers[key] : null; } } }
然后在WebApiConfig 的 Register 中添加
config.Services.WordStr(typeof(IHttpControllerSelector), new VersionControllerSelector(config));
最后我们就可以以差此外版本号,来访谒差此外controller了。
WebApi的多版本打点