Web Api源码(路由注册)
这篇文章只是我学习Web API框架的输出,学习方法还是输出倒逼输入比较行得通,所以不管写的好不好,坚持下去,肯定有收获。篇幅比较长,仔细思考阅读下来大约需要几分钟。
做.NET开发有好几年时间了,从很久之前的WebForm到MVC,再到目前前后端分离模式下RESTful风格的 Web API ,相信这些Web框架很多人都或多或少的用过,也算见证了NET Web端的某一阶段的发展吧,同时很多技术随着发展和迭代,以及前后端分离模式的普及和兴起,用的机会少了,难免可能觉得已经过时了,同时现在流行的Web框架太多太多,不局限于.Net,同样也很优秀,例如:
Java的Spring | Hibernate
Python的Django | Flask
Node的Express和Koa
其实最重要的不是用了多少,知道多少,而是有多少沉淀,在使用领域虽然可能存在过时了,但是从技术的角度,框架设计的思想、代码风格,技术点的使用把控、甚至变量声明等等,都值得我们去学习。
分享方式
- Web API 路由注册和路由处理通过阅读源代码以及边说明的的方式来阐述。
- Web API 管道组装和扩展虽然我们在阅读源码时会接触到它,但我仍然会用
Demo的方式来说明它.- Web API 管道组装和扩展我觉得它设计的真的很棒,忍不住要单独拎出来说一下,虽然有可能把自己讲懵,但我仍然想尝试一下。
1. Web API 路由简介
1.基本介绍
一个ASP.NET的Web应用具有一个全局的路由表,它是通过一个RouteTable类中的一个类型为RouteCollection的Routes静态属性来表示的。

为什么这么说呢?或许这样说不太好理解,用一个简单的例子来说明,我们修改Api框架启动时,注册路由的方式,改为直接用 RouteTable.Routes来添加,这种做法跟框架提供的是一样的,最终都是将路由添加到一个地方。
在针对于路由表这一点上面不仅仅只有WebAPI是这么做的,他同样适用于WebForm 和MVC 同样可以直接在应用程序启动时网路由表中直接添加数据,不过此处只为了证实上述描述,在日常开发中是否可以这样用,完全取决于你自己。
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个重要的静态属性Configuration、DefaultHandler、DefaultServer
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也就是说,在MapHttpRoute中CreateRoute()是由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源码(路由注册)的更多相关文章
- Web API 源码剖析之默认消息处理程序链之路由分发器(HttpRoutingDispatcher)
Web API 源码剖析之默认消息处理程序链-->路由分发器(HttpRoutingDispatcher) 我们在上一节讲述了默认的DefaultServer(是一个类型为HttpServer的 ...
- Web API 源码剖析之默认消息处理程序链--》路由分发器(HttpRoutingDispatcher)
我们在上一节讲述了默认的DefaultServer(是一个类型为HttpServer的只读属性,详情请参考 Web API 源码剖析之全局配置).本节将讲述DefaultHandler(是一个Http ...
- Web API源码剖析之HttpServer
Web API源码剖析之HttpServer 上一节我们讲述全局配置.本节将讲述全局配置的DefaultServer,它是一个HttpServer类型. 主要作用就是接受每一次请求,然后分发给消息处理 ...
- Web API 源码剖析之全局配置
Web API 源码剖析之全局配置 Web API 均指Asp.net Web API .本节讲述的是基于Web API 系统在寄宿于IIS. 本节主要讲述Web API全局配置.它是如何优雅的实现 ...
- Web API 源码剖析之默认配置(HttpConfiguration)
Web API 源码剖析之默认配置(HttpConfiguration) 我们在上一节讲述了全局配置和初始化.本节我们将就全局配置的Configuration只读属性进行展开,她是一个类型为HttpC ...
- Dubbo源码学习--注册中心分析
相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 注册中心 关于注册中心,Dubbo提供了多个实现方式,有比较成熟的使用zookeeper 和 redis 的 ...
- Web API框架学习——路由(一)
HttpConfiguration(ASP.NET Web API管道的配置是通过HttpConfiguration来完成) : 包括路由注册在内的对整个ASP.NET Web API管道的配置是通过 ...
- Android 如何在Eclipse中查看Android API源码 及 support包源码
当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都是已经写好的方法和控件,可是我们只是在搬来使用,不知道它的原理,它是如何被实现的.android系统是开源的,所以谷歌官方 ...
- 【转】Android 如何在Eclipse中查看Android API源码 及 support包源码
原文网址:http://blog.csdn.net/vipzjyno1/article/details/22954775 当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都 ...
随机推荐
- remote debug 的详细配置
一.remote debug 的简单介绍 何为远程debug,项目写完后就需要进入到测试环节,将代码打包发布到测试环境(服务器)上.这时候测试人员测试出一个缺陷(bug).由于代码已经发布到测试环境, ...
- 用maven建立一个工程3
在文件夹里面创建一个新文件夹把工程建立在里面
- 2.安装Spark与Python练习
一.安装Spark <Spark2.4.0入门:Spark的安装和使用> 博客地址:http://dblab.xmu.edu.cn/blog/1307-2/ 1.1 基础环境 1.1.1 ...
- Effective Java —— 用私有构造器或枚举类型强化单例属性
本文参考 本篇文章参考自<Effective Java>第三版第三条"Enforce the singleton property with a private construc ...
- 小技巧之“将Text文件中的数据导入到Excel中,这里空格为分割符为例”
1.使用场景 将数据以文本导出后,想录入到Excel中,的简便方案, 起因:对于Excel的导出,Text导出明显会更方便些 2.将Text文件中的数据导入到Excel中,这里空格为分割符为例的步骤 ...
- 移动端比1px还小的border
巧用border 在移动端 经常出现border,细边框但有的时候 产品大大1px甚至乎会觉得不够细那么要如何写出比1px还要小的border下面是代码 希望对大家有所帮助 .thinner-bord ...
- vue+koa2即时聊天,实时推送比特币价格,爬取电影网站
技术栈 vue+vuex+vue-router+socket.io+koa2+mongodb+pm2自动化部署+图灵机器人+[npm script打包,cdn同步,服务器上传一个命令全搞定] 功能清单 ...
- CCF201512-2消除类游戏
问题描述 消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消 ...
- 进入React的世界
一. React 是什么 1. 声明式写法 2. 组件化 3. 一次学习, 随处编写 二. 为什么要学习React 1. 大厂加持 - Facebook 2. 最流行, 使用人数最多, 最被开发者喜爱 ...
- GitHub Pages + Hexo搭建个人博客网站-github风格-采坑记录
目录 1.本机安装nodejs 2.github上创建仓库 3.安装hexo 4.hexo主题 5.配置主题 6.添加文章 7.使用分类和标签 8.增加文章目录 9.推送github 使用github ...