net core 管道中间件源码分析
这段时间阅读了net core核心源码,对不太理解的点有了一定理解,希望对大家有所帮助.先来说说HTTP,HTTP是一种协议(协议:约定好了字符串格式,客户端和服务器通过这个协议都能理解字符串格式,解析后并各自处理,并相互返回)
简单描述下net core管道: 把每个HTTP请求,转换成HTTPContext(客户端提交上来的东西都装里面了),交给每一个中间件(委托)做不同的处理.形成最终结果通过HTTP返回给客户端
每个中间件可以处理完后交由下一个中间件或者结束执行返回结果给客户端.
具体如何实现的我们开始分析源码基于(2.2.0)版本
1.核心(中间件)
上面说到HTTPContext 需要经过好几个环节的处理加工,中间件必须得有个东西来装下它吧
public delegate Task MyRequestDelegate(myHttpContext context);
定义了一个(中间件) ,取名MyRequestDelegate,必须传入参数 HTTPContext(Http协议的具体内容的封装)
中间件应该有很多,得有个东西装下它
private readonly IList<Func<MyRequestDelegate, MyRequestDelegate>> _components = new List<Func<MyRequestDelegate, MyRequestDelegate>>();
(其实是生成中间件的方法的列表,返回值是中间件委托)
很常见的List,里面放了N个返回结果是MyRequestDelegate中间件委托的方法,有人会问这Func<MyRequestDelegate, MyRequestDelegate> 是个啥
就是一个 输入和输出都是MyRequestDelegate方法的缩写,我们来自己写一个Func<MyRequestDelegate, MyRequestDelegate>
public static MyRequestDelegate websocketRequestDelegate1(MyRequestDelegate next404) { // 返回一个匿名MyRequestDelegate,系统自动命名XXXX我也不知道是啥 // return async context => { await context.WriteLIne(); }; }
是不是很常见的方法而已,然后我们把生成中间件的Func加入到列表去
public IMyApplicationBuilder Use(Func<MyRequestDelegate, MyRequestDelegate> middleware) { _components.Add(middleware); return this; }
很眼熟的Use(Startup),所有的生成MyRequestDelegate的Func最终都会通过这个Use加入到中间件列表中,看下图net core ,UseMiddleware源码也是调用了Use
添加了这么多生成中间件的Func到列表里了好像他们都没啥关联啊,怎么互相串联起来的呢.关键代码:
// 微软串联各个中间件源码Build方法
public MyRequestDelegate Build() { MyRequestDelegate next404 =
delegate (myHttpContext context) { context.Code = 404; return Task.CompletedTask; };
//核心代码 把一个个中间件串起来,串糖葫芦一样 后一个关联前一个 foreach (Func<MyRequestDelegate, MyRequestDelegate> taskRequestDelegate in _components.Reverse())// 如果是空的 程序就整个中间件就一个404 直接返回404 ,程序启动的时候会调用404中间件 { next404 = taskRequestDelegate(next404); //关键难点看下图 } return next404; }
启动程序 main.cs
IMyApplicationBuilder app = new MyApplicationBuilder();
app.Use(websocket);
app.Use(mvc);
app.Use(auth);
app.Build();
--中间件Class.cs
//返回websocket 自己功能的执行代码 + 404 中间件执行代码的一个方法体
//生成一个新的 MyRequestDelegate public static MyRequestDelegate websocket(MyRequestDelegate next404) { // 返回一个匿名MyRequestDelegate,系统自动命名XXXX我也不知道是啥 // return async context => { await context.WriteLIne(); await next404(context); }; }
// 返回mvc 自己功能中间件的 public static MyRequestDelegate mvc(MyRequestDelegate websocke_And_next404) { return async context => { await context.WriteLIne();// 中间件自己的处理逻辑 await websocke_And_next404(context);// 404和websocket中间件调用 }; }
执行过程:
1.定义了2个自己拓展的生成中间件的 Func<MyRequestDelegate, MyRequestDelegate> 名字叫websocket和mvc
2.把websocket 和 mvc加入到IMyApplicationBuilder 的 _components (Func<MyRequestDelegate, MyRequestDelegate>列表)
3.开始执行组装Build
代码不便于理解,画了个图方便理解,看下图:
从上图可以看出,循环开始执行后 的每一次做了什么, next404实际上只是重新指向了(c++叫函数指针)一个新生成的中间件,是新的,并不是覆盖.
记住了这个关键,就知道每一个中间件是如何串在一起,并执行每一个中间件的了, 所有循环结束后返回 最后一个新生成的中间件的地址
return next404;//next404 指向了内存地址3(委托引用的实际方法)
net core 的学习就说到这,希望对大家有所帮助, 有说的不对的地方请纠正(代码是模仿微软底层中间件源码写的,语文不太好,各位大佬谅解下哈!!!)
有时间的话打算写一个net core系列.分析分析net core自带的mvc中间件. 验证中间件,过滤器中间件,拦截等中间件等等相关源码