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开发文档时候,上面的每个类,以及类的各个方法都 ...
随机推荐
- Netty学习摘记 —— 深入了解Netty核心组件
本文参考 本篇文章是对<Netty In Action>一书第三章"Netty的组件和设计"的学习摘记,主要内容为Channel.EventLoop.ChannelFu ...
- hackgame2018_签到
hackgame2018_签到 进入题目得到如下提示 尝试提交 发现这个输入框长度做了限制我们将前端js修改一下 然后提交以下这样就发现了flag这题比较简单--
- vulnhub靶机djinn:1渗透笔记
djinn:1渗透笔记 靶机下载地址:https://www.vulnhub.com/entry/djinn-1,397/ 信息收集 首先我们嘚确保一点,kali机和靶机处于同一网段,查看kali i ...
- PWA 时代的移动端图片优化新思路
图片通常是移动端网页中最占流量的资源.在很多类型的网站中(比如电商.社区),图片占据了网页的大部分空间.优化图片的质量和加载速度成为提高用户体验的重要途径. 传统方案的弊端 目前有一些被广泛应用的方案 ...
- vue2实现搜索结果中的搜索关键字高亮
// 筛选变色 brightenKeyword(val, keyword) { val = val + ''; if (val.indexOf(keyword) !== -1 && k ...
- mysql在cmd中查询到的汉字乱码问题解决 方法一
只要执行如上两个 set character_set_connection = gbk; set character_set_results= gbk; 将编码格式转换成gbk即可
- 使用cookie/session实现简单的用户信息的保存
cookie一般用来存储非关键信息 , 用户名和密码等敏感信息一般采用session 来存储:cookie和session的最大区别是当服务器端存储session 之后,用户再次请求时候只是请求了一个 ...
- HDMS(Headend Device Management System)软件下载
进入官网http://www.pbi-china.com/CHS/index.aspx点击右下角的下载通道.
- 6.S081-2021-Lab3 Pgtbl学习笔记
Speed up system calls 根据hints查看kernel/proc.c中的函数proc_pagetable // kernel/proc.c // Create a user pag ...
- SpringMVC的数据响应方式-页面跳转
1.返回字符串形式 直接返回字符串:此种方式会返回字符串与视图解析器的前后缀拼接后跳转 有关视图解析器的拼接请访问此地址 注意:WEB-INF下的资源一般不能访问,因为转发是服务器的操作所以可以访问到 ...