这篇文章只是我学习Web API框架的输出,学习方法还是输出倒逼输入比较行得通,所以不管写的好不好,坚持下去,肯定有收获。篇幅比较长,仔细思考阅读下来大约需要几分钟。

做.NET开发有好几年时间了,从很久之前的WebFormMVC,再到目前前后端分离模式下RESTful风格的 Web API ,相信这些Web框架很多人都或多或少的用过,也算见证了NET Web端的某一阶段的发展吧,同时很多技术随着发展和迭代,以及前后端分离模式的普及和兴起,用的机会少了,难免可能觉得已经过时了,同时现在流行的Web框架太多太多,不局限于.Net,同样也很优秀,例如:

Java的Spring | Hibernate

Python的Django | Flask

Node的Express和Koa

其实最重要的不是用了多少,知道多少,而是有多少沉淀,在使用领域虽然可能存在过时了,但是从技术的角度,框架设计的思想代码风格技术点的使用把控甚至变量声明等等,都值得我们去学习。

分享方式

  1. Web API 路由注册路由处理通过阅读源代码以及边说明的的方式来阐述。
  2. Web API 管道组装和扩展虽然我们在阅读源码时会接触到它,但我仍然会用Demo的方式来说明它.
  3. Web API 管道组装和扩展我觉得它设计的真的很棒,忍不住要单独拎出来说一下,虽然有可能把自己讲懵,但我仍然想尝试一下。

1. Web API 路由简介
1.基本介绍

一个ASP.NET的Web应用具有一个全局的路由表,它是通过一个RouteTable类中的一个类型为RouteCollectionRoutes静态属性来表示的。

为什么这么说呢?或许这样说不太好理解,用一个简单的例子来说明,我们修改Api框架启动时,注册路由的方式,改为直接用 RouteTable.Routes来添加,这种做法跟框架提供的是一样的,最终都是将路由添加到一个地方。

在针对于路由表这一点上面不仅仅只有WebAPI是这么做的,他同样适用于WebFormMVC 同样可以直接在应用程序启动时网路由表中直接添加数据,不过此处只为了证实上述描述,在日常开发中是否可以这样用,完全取决于你自己。

1.框架提供的

public static void Register(HttpConfiguration config)
{
// Web API 框架提供的路由
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{Action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}

2.通过直接路由表添加

 //在WebApiConfig.Register中修改注册路由.
public static void Register(HttpConfiguration config)
{
//验证路由是否加到全局路由表
var ro = new { id = RouteParameter.Optional };
//获取默认WebAPI路由处理器
IRouteHandler routeHandler = HttpControllerRouteHandler.Instance;
RouteValueDictionary defaults = new RouteValueDictionary(ro);
Route route = new Route("api/{controller}/{Action}/{id}", defaults, routeHandler);
RouteTable.Routes.Add("DefaultApi", route);
}
2.思考的问题

1.我们思考RouteCollection为什么是静态的?

因为静态对象会一直存在内存中,直到程序池下一次回收之前.`

2.我们在用WebAPI开发应用接口的时候,前端Url请求是怎么通过路由到达我们对应的控制器和Action的?

其实是根据路由来控制的,至于怎么控制,怎么实现,后面会慢慢介绍.

3.路由控制如何路由呢?

1.先注册路由,再将路由和处理器绑定。

2.然后用户请求根据请求的Url 匹配对应的处理器,再由处理器进行路由模板规则解析。

3.根据解析到的规则反射找到Contrller和Action。

2. Web API 路由注册

路由注册这一部分在MVC5之后就有2部分了,新增了一个特性路由,此次不做分享,后续有机会再补上..我们看下简单的路由注册图,当然其中还有很多东西,只是画的比较简陋,

上面的所表示的流程中,我们作为使用框架的开发人员,关注的只是其中一小部分,从代码角度能看到,就只有如下很简单的几句代码,并且连这个代码都是框架生成的,从另一个角度也说明框架的封装比较完整和强大,让开发人员只关注自己的业务就行了

注册路由流程部分

1.注册方式

1.在Web Api程序启动时,首先调用GlobalConfiguration.Configure(WebApiConfig.Register)方法,这个方法接收的参数是一个Action<HttpConfiguration> 作为参数,看到Action我们的第一反应就是作为回调执行, 框架给我们预留了扩展空间,用户扩展的内容在内部执行

2.说白了GlobalConfiguration.Configure()方法的参数,需要一个委托,而委托的本质就是一个无返回值,包含HttpConfiguration类型的实例作为参数的方法,我们转到框架定义的WebApiConfig.Register()方法,毫无疑问它符合要求,所以这个方法就是在框架中被GlobalConfiguration.Configure() 执行的回调,而这个回调的作用就是注册路由

注册路由作为框架GlobalConfiguration.Configure的回调,与上图中相等

2.GlobalConfiguration

我们发现更多的信息在GlobalConfiguration类中,继续一步步解读,打开源码找到GlobalConfiguration这个类来看

1.它是个静态类包含一个重要的方法Configure(Action configurationCallback)

2.它包含3个重要的静态属性ConfigurationDefaultHandlerDefaultServer

3.三个属性被调用时就已经初始化了,但被Lazy类型包裹,说明是被延迟执行,具体延迟执行的时机就是调用它的Value属性时。

4.目前在路由注册阶段只介绍Configuration,剩下2个在路由解析部分在分享.

1.我们首先看GlobalConfiguration.Configure(Action configurationCallback) 的内部做了2件事,执行我们扩展的回调,也就是注册路由的业务,然后检查初始化HttpConfiguration

执行回调需要的参数,正是第一个属性Configuration 通过该类型的Routes属性的MapHttpRoute扩展方法来往路由表中添加数据。可以知道我们只要搞清楚了HttpConfiguration类型的Configuration的来源,就能搞清楚很多事情。

我们找到HttpConfiguration类型的Configuration是怎么初始化的,先展开它,查看代码看到他是由内部的CreateConfiguration()方法创建的

3.注册流程步骤

1.在CreateConfiguration()HttpConfiguration被构造时我们经过查看上下文发现

1.传入一个HostedHttpRouteCollection对象,并在内部赋值给HttpRouteCollection类型的_routes属性

2.HostedHttpRouteCollection在构造时,传入了我们的全局路由表RouteTable.Routes

2.我们找到映射路由的扩展方法MapHttpRoute可以知道我们调用它的Route属性是一个HostedHttpRouteCollection也就是说,在MapHttpRouteCreateRoute()是由HostedHttpRouteCollection来调用的

3.继续转到HostedHttpRouteCollection类中的CreateRoute()内部看到它返回一个HostedHttpRoute而它就是实现IHttpRoute的实例。

4.继续深入在HostedHttpRoute构造时,内部有一个Route类型的OriginalRoute属性,它被赋值为继承自(Route:RouteBase)HttpWebRoute类型。

5.在HttpWebRoute初始构造时传入了几个极为重要的参数路由模板IRouteHandler类型HttpControllerRouteHandler以及一个IHttpRoute类型的HostedHttpRoute,然后程序返回,注意此处的IRouteHandler可以理解为是路由的处理器.最终在HostedHttpRouteCollection对象上调用routes.Add(name, route)添加 路由模板名字处理程序.

4.总结

现在我们对Web Api中的路由注册部分已经做了一个简单的介绍,并且一步一步理解了源码实现的逻辑,其实说到本质,路由注册只做了一件事,就是将路由模板规则和路由处理器提前绑定,客户端按照对应的规则请求来匹配对应的路由处理器做最终的处理,而目前框架内置的路由处理器就是一个HttpControllerRouteHandler,后面部分进入路由处理,如果在阅读过程中有任何疑问欢迎随时和我讨论, 强烈建议在阅读本篇分享建立了粗略的知识点之后,有时间的话自己先下载Web Api源码进行阅读,这样可以帮助更好的理解。

Web Api源码(路由注册)的更多相关文章

  1. Web API 源码剖析之默认消息处理程序链之路由分发器(HttpRoutingDispatcher)

    Web API 源码剖析之默认消息处理程序链-->路由分发器(HttpRoutingDispatcher) 我们在上一节讲述了默认的DefaultServer(是一个类型为HttpServer的 ...

  2. Web API 源码剖析之默认消息处理程序链--》路由分发器(HttpRoutingDispatcher)

    我们在上一节讲述了默认的DefaultServer(是一个类型为HttpServer的只读属性,详情请参考 Web API 源码剖析之全局配置).本节将讲述DefaultHandler(是一个Http ...

  3. Web API源码剖析之HttpServer

    Web API源码剖析之HttpServer 上一节我们讲述全局配置.本节将讲述全局配置的DefaultServer,它是一个HttpServer类型. 主要作用就是接受每一次请求,然后分发给消息处理 ...

  4. Web API 源码剖析之全局配置

    Web API 源码剖析之全局配置 Web API  均指Asp.net Web API .本节讲述的是基于Web API 系统在寄宿于IIS. 本节主要讲述Web API全局配置.它是如何优雅的实现 ...

  5. Web API 源码剖析之默认配置(HttpConfiguration)

    Web API 源码剖析之默认配置(HttpConfiguration) 我们在上一节讲述了全局配置和初始化.本节我们将就全局配置的Configuration只读属性进行展开,她是一个类型为HttpC ...

  6. Dubbo源码学习--注册中心分析

    相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 注册中心 关于注册中心,Dubbo提供了多个实现方式,有比较成熟的使用zookeeper 和 redis 的 ...

  7. Web API框架学习——路由(一)

    HttpConfiguration(ASP.NET Web API管道的配置是通过HttpConfiguration来完成) : 包括路由注册在内的对整个ASP.NET Web API管道的配置是通过 ...

  8. Android 如何在Eclipse中查看Android API源码 及 support包源码

    当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都是已经写好的方法和控件,可是我们只是在搬来使用,不知道它的原理,它是如何被实现的.android系统是开源的,所以谷歌官方 ...

  9. 【转】Android 如何在Eclipse中查看Android API源码 及 support包源码

    原文网址:http://blog.csdn.net/vipzjyno1/article/details/22954775 当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都 ...

  10. 如何在Eclipse中查看Android API源码以及support包源码

    http://my.eoe.cn/futurexiong/archive/181.html 开发第三方Android应用的,大多数人应该还是Eclipse结合ADT来开发.那么大多数时候我们可能希望点 ...

随机推荐

  1. Java中创建对象的几种方式

    Java中创建对象的五种方式: 作为java开发者,我们每天创建很多对象,但是我们通常使用依赖注入的方式管理系统,比如:Spring去创建对象,然而这里有很多创建对象的方法:使用New关键字.使用Cl ...

  2. WPF学习之路(十二)控件(HeaderedContent控件)

    GroupBox 用来组织多种控件的常见控件,因为是内容空间,只能直接包含一项,需要使用面板一类的中间空间. Header和Content可以是任意元素 <GroupBox> <Gr ...

  3. 【MYSQL】update/delete/select语句中的子查询

    update或delete语句里含有子查询时,子查询里的表不能在update或是delete语句中,如含有运行时会报错:但select语句里含有子查询时,子查询里的表可以在select语句中. 如:把 ...

  4. Spring配置文件解析--依赖注入

    1.构造器注入基于构造器的DI通过调用带参数的构造器来实现,每个参数代表着一个依赖.此外,还可通过给stattic工厂方法传参数来构造bean.构造器参数解析根据参数类型进行匹配,如果bean的构造器 ...

  5. windows类书的学习心得(转载)

    原文网址:http://www.blogjava.net/sound/archive/2008/08/21/40499.html 现在的计算机图书发展的可真快,很久没去书店,昨日去了一下,真是感叹万千 ...

  6. 数据结构(主席树):HZOI 2016 采花

    [题目描述] 给定一个长度为n,包含c种颜色的序列,有m个询问,每次给出两个数l,r,表示询问区间[l,r]中有多少种颜色的出现次数不少于2次. 本题强制在线,对输入的l,r进行了加密,解密方法为: ...

  7. java编程思想笔记(第一章)

    Alan Kay 第一个定义了面向对象的语言 1.万物皆对象 2.程序是对象的集合,他们彼此通过发送消息来调用对方. 3.每个对象都拥有由其他对象所构成的存储 4.每个对象都拥有其类型(TYpe) 5 ...

  8. RabbitMQ第四篇:Spring集成RabbitMQ

    前面几篇讲解了如何使用rabbitMq,这一篇主要讲解spring集成rabbitmq. 首先引入配置文件org.springframework.amqp,如下 <dependency> ...

  9. ●BZOJ 2669 [cqoi2012]局部极小值

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题解: 容斥,DP,DFS 先看看 dp 部分:首先呢,X的个数不会超过 8个.个数很 ...

  10. hdu 5455 (2015沈阳网赛 简单题) Fang Fang

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5455 题意就是找出所给字符串有多少个满足题目所给条件的子串,重复的也算,坑点是如果有c,f以外的字符也是不 ...