ASP.NET Core HTTP 管道中的那些事儿

前言

马上2016年就要过去了,时间可是真快啊。

上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情。首先是 NPOI 的移植工作,移植过后还有一些Bug需要修复,然后一个事情是一个有关于分布式架构中消息一致性的一个中间件设计开发工作,还有就是博客还要坚持写,最后就是还有好几本书需要读,以及消化学习,所以深深感觉到时间不够用。废话不多说了,进入主题。

大部分中间件都是要依赖于 HTTP 管道和 HttpAbstractions 提供的上下文的,所以有必要先介绍一下 ASP.NET Core 在管道中封装了什么,了解清楚之后有助于更高的进阶学习。你看不懂也没有关系,对这些概念有一个认识就可以了,不需要你精通每一步都具体做了哪些东西,达到会用就是我的目的。因为我觉得随着你以后开发的深入,对这些东西使用多了之后,自然会想了解更多,到那个时候,你就会去看源码了。

IApplicationBuilder

IApplicationBuilder 是应用大家最熟悉它的地方应该就是位于 Startup.cs 文件中的 Configure 方法了吧

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory){app.UseDeveloperExceptionPage();app.UseStaticFiles();app.UseMvc();
}

IApplicationBuilder 就像其名字一样,其实很简单,就是对内做了一个接口封装,对外提供了一个扩展,具体来说就是

对内封装了

  • IServiceProvider ApplicationServices { get; set; }:应用程序使用的服务,就是ConfigureServices注入的那些。

  • IFeatureCollection ServerFeatures { get; }: 工具箱对象,下面会提到的。

  • IDictionary<string, object> Properties { get; } :横跨各个中间件,在他们之间共享数据。

对外扩展了

  • IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware):注册中间件

还有一个 Build 用来返回管道最终的 HttpContext 状态

  • RequestDelegate Build(); : 最终的 RequestDelegate 形态

没什么复杂的东西,就这几个东西需要了解,下面是一个 IApplicationBuilder 的贴图,看起来应该会更直观。

那 RequestDelegate 又是什么东西呢?

RequestDelegate

RequestDelegate 是一个委托,是以委托形式对 HttpContext 的封装,在 ASP.NET Core 中也是非常重要的一个对象,先看一下定义吧。

namespace Microsoft.AspNetCore.Http{    public delegate Task RequestDelegate(HttpContext context);
}

为什么说这个对象很重要呢,因为在管道中所有的中间件都是直接或者间接的使用到它来做一些功能,因为它包装这 HttpContext 的嘛,而在Web开发中 HttpContext 的地位又是如此的高,接下来就说说 HttpContext

HttpContext

HttpContext 应该是做Web开发最熟悉的一个对象了,在这个对象中,封装着Http整个管道中的关键对象信息,这个对象同时伴随着整个管道中传输,也就是会经历整个请求的生命周期,所以这个对象非常重要,也是学习Web开发的一个基础知识。

与传统 .NET Framework 中的 System.Web.HttpContext 不同的是,在 ASP.NET Core 中 HttpContext 是一个抽象类,位于 Microsoft.AspNetCore.Http 命名空间下。它有一个默认的实现叫 DefaultHttpContext 位于 Microsoft.AspNetCore.Http 程序集。

我们知道以前的 System.Web.HttpContext 是怎么创建的吧?

在传统ASP.NET程序中,IIS接收到请求之后,会交给 aspnet_isapi.dll 这个程序集,程序集启动 ASP.NET 运行环境,然后调用 ISAPIRuntime 进行封装,封装之后就是一个 HttpWorkRequest 对象了,然后由 HttpRuntime将其转化为一个HttpContext。

所以在System.Web.HttpContext中,其构造函数为 HttpWorkerRequest

namespace System.Web
{   
   public sealed class HttpContext : IServiceProvider, IPrincipalContainer{      
      public HttpContext(HttpWorkerRequest wr);} }

也就是说其实构建HttpContext所有的信息都是来自于 IIS 传递下来的 HttpWorkerRequest

现在,忘了它吧,是的全部忘掉,这个时候你又要骂微软了,尼玛当年为了面试这个东西不知道背了多少遍。 =_=

没办法,时代要发展要进步,我们也需要不断的学习,那在 ASP.NET Core 中,没有了 IIS ,它的 HttpContext 又是如何生成的呢? 构建 HttpContext 所需的信息又怎么来的呢? 客官不要着急,听我慢慢分解

IFeatureCollection

这里就需要先说一下另外一个比较重要接口了,它就是 IFeatureCollection 接口,这个接口是干嘛的呢? 我们先看一下它的定义:

public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>
{bool IsReadOnly { get; }int Revision { get; }object this[Type key] { get; set; }TFeature Get<TFeature>();    void Set<TFeature>(TFeature instance);
}

看到这个接口的定义应该能够明白其功能了,接口继承于IEnumerable<KeyValuePair<Type, object>> 说明接口是一个键值对的集合,我们给接口取个名字吧,叫“工具箱”。

有些同学应该猜出来了,是的,ASP.NET Core中构建 HttpContext 就是所有需要的组件都是来自于 工具箱,那么 工具箱 里面都有什么呢?可以看到工具箱里面有 IHttpRequestFeature, IHttpResponseFeature, ISessionFeature 等等还有很多就不一一列举了,正是由于这一个一个的工具箱里面的工具,最终构建成为了整个 HttpContext 对象。我们来看一下 HttpContext 对象的构造函数:

namespace Microsoft.AspNetCore.Http{    
public class DefaultHttpContext : HttpContext{        public DefaultHttpContext(IFeatureCollection features)        {Initialize(features);}} }

没错吧,有同学可能要问了,工具箱里面的这些工具什么时候初始化的呢? 先别急,我们先看看我们熟悉的 Request 和 Response。

HttpRequest

同样在 ASP.NET Core ,HttpRequest 也成为了一个抽象类,它的默认实现叫 DefaultHttpRequest,主要是封装浏览器对服务器的请求的各种数据,包括浏览器请求的网址,查询字符串数据或表单数据等等...

不一一详细介绍了,都是很简单的内容。

HttpResponse

HttpResponse 也成为了一个抽象类,它的默认实现叫 DefaultHttpResponse,主要是是服务器接收到浏览器的请求后,处理返回结果常用的一个对象。

ASP.NET Core 管道

是时候该解释一下上面的 工具箱 初始化的问题了,我想我用一个图来直接说明管道中的请求再合适不过了,下面就是一个 ASP.NET Core 整个服务端构建管道一个流程图:

从图中可以看到,RequestDelegate 携带着 HttpContext 一路经过各种 Server、Hosting 等,最终到达了由 IApplicationBuilder 构建出来的 Application pipeline 这一管道区域,然后再经过各种中间件处理,最终构建出来了我们的 Response,而我们的工具箱 也正是在这个过程中变得 “ 饱满 ” 起来。

有一个需要知道的知识点就是,中间件是怎么样添加或者叫注册到管道中的呢? 又是如何被应用起来的呢?

上面的图可以看到,橙色区域的 Application pipeline 是由 IApplicationBuilder 构建起来的。也就是说我们可以在 IApplicationBuilder 做点什么东西来添加我们的中间件。 是的 IApplicationBuilder 暴露出来了一个 IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); 方法来让我们注册中间件,也就是说位于 Startup.cs 文件中的 Configure 方法。

那么又是怎么样应用起来的呢? IApplicationBuilder 在 Hosting 中有一个 IApplicationBuilderFactory 的对象,Hosting 通过这个Factory 创建之后就会传递到了 HostingApplication 对象中,最后由 IWebHost 对象调用 IServer 对象的Start 同时把 HostingApplication传递进去来最终启动服务端。可以对照上面的图理解一下。

总结

在本篇中,我们知道了 ASP.NET Core Http 管道中的几个对象,他们分别是 IApplicationBuilder , RequestDelegate , HttpContext , HttpRequest , HttpResponseIFeatureCollection 等,然后也知道了他们之间的关系,接着我们通过一个管道流程图知道了他们的调用关系,也知道了如何向管道中注册中间件。

原文地址: http://www.cnblogs.com/savorboard/p/aspnetcore-http-pipeline.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327373.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解Java多线程编程中LockSupport类的线程阻塞用法

转载自 详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类&#xff0c;提供了基本的线程同步原语。LockSupport实际上是调用了Unsafe类里的函数&#xff0c;归结到Unsafe里&#xff0c;只有两个函数&#xff1a; public native…

javaWeb服务详解(含源代码,测试通过,注释)

javaweb服务分为两个部分&#xff0c;一部分是web服务端&#xff0c;另一部分就是你调用的客户端了。首先我说下实现web服务的简单思路&#xff1a; 一、服务器端实现&#xff1a; 1.添加webservice jar包 spring支持 2.添加一个web服务 3.在实体类和接口以及对应的实现类中添…

基本属性---Linux

基本属性 看懂文件属性 Linux系统是一种典型的多用户系统&#xff0c;不同的用户处于不同的地位&#xff0c;拥有不同的权限。为了保护系统的安全性&#xff0c;Linux系统对不同的用户访问同一文件&#xff08;包括目录文件&#xff09;的权限做了不同的规定。 在Linux中我们…

Java中的增强for循环的实现原理与坑

转载自 Java中的增强for循环的实现原理与坑 在JAVA中&#xff0c;遍历集合和数组一般有以下三种形式&#xff1a; for (int i 0; i < list.size(); i) {System.out.print(list.get(i) ","); }Iterator iterator list.iterator(); while (iterator.hasNext())…

Prometheus 系统监控方案

最近一直在折腾时序类型的数据库&#xff0c;经过一段时间项目应用&#xff0c;觉得十分不错。而Prometheus又是刚刚推出不久的开源方案&#xff0c;中文资料较少&#xff0c;所以打算写一系列应用的实践过程分享一下。 Prometheus 是什么&#xff1f; Prometheus是一套开源的监…

文件内容查看---Linux

文件内容查看 概述 Linux系统中使用以下命令来查看文件的内容&#xff1a; cat 由第一行开始显示文件内容tac 从最后一行开始显示&#xff0c;可以看出 tac 是 cat 的倒着写&#xff01;nl 显示的时候&#xff0c;顺道输出行号&#xff01;more 一页一页的显示文件内容less 与…

怎样批量获取文件名,批量提取文件名 文件名读取windows 批处理文件

https://jingyan.baidu.com/article/cdddd41cb0776f53cb00e1e4.html https://jingyan.baidu.com/article/cdddd41cb0776f53cb00e1e4.html 如图&#xff0c;这个文件夹中有一些名字比较奇特的文件&#xff0c;接着我们就开始获取这些文件的文件名。 如图&#xff0c;文件在一…

大三那年在某宝8块钱买的.NET视频决定了我的职业生涯

前言 谨以此文献给那些还在大学中迷茫的莘莘学子们&#xff01; 韩愈在《师说》中提出了作为师者应该做的三件事&#xff1a;传道、授业、解惑。 1.传道&#xff1a;培养学生的道德观 2.授业&#xff1a;传授学生专业技能 3.解惑&#xff1a;解答学生内心的迷茫迷惑 曾几何时&a…

为什么说Java中只有值传递(另一种角度)

转载自 为什么说Java中只有值传递 对于初学者来说&#xff0c;要想把这个问题回答正确&#xff0c;是比较难的。在第二天整理答案的时候&#xff0c;我发现我竟然无法通过简单的语言把这个事情描述的很容易理解&#xff0c;遗憾的是&#xff0c;我也没有在网上找到哪篇文章可以…

链接(了解)---Linux

链接&#xff08;了解&#xff09; Linux 链接分两种&#xff0c;一种被称为硬链接&#xff08;Hard Link&#xff09;&#xff0c;另一种被称为符号链接&#xff08;Symbolic Link&#xff09;。 情况下&#xff0c;ln 命令产生硬链接。 硬链接 硬连接指通过索引节点来进行…

解决: -bash: docker-compose: command not found、linux 安装 docker-compose

https://blog.csdn.net/jiangyu1013/article/details/84570872 https://blog.csdn.net/guoshaoliang789/article/details/96878731 解决&#xff1a; -bash: docker-compose: command not found、linux 安装 docker-compose 微风--轻许-- 2018-11-27 18:06:01 26470 收藏 8 …

.NET Task揭秘(一)

Task为.NET提供了基于任务的异步模式&#xff0c;它不是线程&#xff0c;它运行在线程池的线程上。本着开源的精神&#xff0c; 本文以解读基于.NET4.5 Task源码的方式来揭秘Task的实现原理。 Task的创建 Task的创建方式主要有2种&#xff1a;Task.Run 和Task.Factory.StartNew…

javaWeb服务详解(含源代码,测试通过,注释) ——Dept的Dao层

IDeptDao.java接口 /** * Title: IDeptDao.java * Package org.dao * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-6-2 上午11:49:15 * version V1.0 */ package org.dao;import java.util.List;import org.entity.D…

Linux(笔记)

开启端口时&#xff0c;宝塔面板和阿里云都要开启 简介 我们为什么要学习Linux linux诞生了这么多年&#xff0c;以前还喊着如何能取代windows系统&#xff0c;现在这个口号已经小多了&#xff0c;任何事物发展都有其局限性都有其天花板。就如同在国内再搞一个社交软件取代腾讯…

自增主键与UUID的优缺点

https://blog.csdn.net/rocling/article/details/83116950 自增主键与UUID的优缺点 rocling 2018-10-17 20:15:02 8062 收藏 8 分类专栏&#xff1a; sql java 文章标签&#xff1a; sql 版权 自增主键 自增ID是在设计表时将id字段的值设置为自增的形式&#xff0c;这样当…

Git 在团队中的最佳实践--如何正确使用Git Flow

我们已经从SVN 切换到Git很多年了&#xff0c;现在几乎所有的项目都在使用Github管理, 本篇文章讲一下为什么使用Git, 以及如何在团队中正确使用。 Git的优点 Git的优点很多&#xff0c;但是这里只列出我认为非常突出的几点。 由于是分布式&#xff0c;所有本地库包含了远程库的…

javaWeb服务详解(含源代码,测试通过,注释) ——Emp的Dao层

IEmpDao的接口 /** * Title: IEmpDao.java * Package org.dao * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-6-2 下午2:53:12 * version V1.0 */ package org.dao;import java.util.List;import org.entity.Emp;/**…

拿到阿里巴巴的实习生Offer就是这么简单

转载自 拿到阿里巴巴的实习生Offer就是这么简单 一、个人简介及面试流程简介 本人本科就读于一个非985非211的一本高校&#xff0c;研究生就读于某985高校&#xff0c;目前研究方向为云计算与大数据。实习内推部门为菜鸟网络&#xff0c;所投的岗位为后台开发Java(包含大数据…

[译] RESTful API 设计最佳实践

https://juejin.im/entry/6844903503953920007 [译] RESTful API 设计最佳实践 阅读 8779 收藏 0 2017-10-16 原文链接&#xff1a; segmentfault.com 原文&#xff1a;RESTful API Design. Best Practices in a Nutshell. 作者&#xff1a;Philipp Hauer 项目资源的URL应该…

Git(笔记)

版本控制 版本控制&#xff08;Revision control&#xff09;是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史&#xff0c;方便查看更改历史记录&#xff0c;备份以便恢复以前的版本的软件工程技术。 实现跨区域多人协同开发追踪和记载一个或者多个文件…