简述asp.net core中间件的实现思路

原文地址:https://www.cnblogs.com/shengyu-kmust/p/11583974.html

一次http请求的过程,就是对一个Request请求进行若干次逻辑处理,并最终设置Response的过程。从代码的实现维度看,由于Request和Response都在HttpContext里,可将此过程表示为“以一个httpContext为输入的委托函数”,即delegate Task RequestDelegate(HttpContext context),为方便此文的描述,我们将此委托函数暂时称为“请求处理逻辑”

而中间件的作用,就是在请求的后面加入一个处理逻辑,这个处理逻辑是以“前一个请求处理逻辑”为输入,并经过中间件自己的处理后,返回一个“新的请求处理逻辑”。所以从代码上可将“中间件”表式为以一个“请求处理逻辑”为输入并返回另一个“请求处理逻辑”的委托,即Func<RequestDelegate,RequestDelegate>。而多个中间件即表示为List<Func<RequestDelegate,RequestDelegate>>。

Asp.net core中间件的核心功能就是如何将一系列的中间件,合并成一个“请求处理逻辑”的过程,即如何将List<Func<RequestDelegate,RequestDelegate>>合并生成一个RequestDelegate。合并逻辑如下

上面的代码有两个地方要注意

1、asp.net core会默认在请求的最后加入一个“404”处理的中间件。

2、合并时,组件是先反序后再循环的

因先加入的中间件要先执行,所以在合并时,第一个中间件要最后合并,即要倒序后再循环合并中间件

如何使用中间件

使用中间件有四种方法:Use、Run、Map和使用Middleware class,但前三种方法最终调用的都是Use方法,我们来看看Use方法的实现逻辑,如下

即use方法只是在中间件列表(_components)的最后再加入一个中间件

下面详细描述四种方法的用法

Use的用法

Ues的用法有两种

用法一

调用IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware),此用法需在middleware委托里自己控制是否要进入下一个中间件,并且要自己创建一个RequestDelegate并返回,写法会比较复杂。

示例如下

用法二

调用IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware),这是一个扩展方法,此方法不用自己创建RequestDelegate并返回,写法比较简洁。它最终调用的方法还是用法一中的实现,此方法的实现代码如下。

示例如下

需注意:上面的两种Use用法,在第二个中间件时,并没有再调用下一个中间件,这是为了确保http请求不会进入到asp.net core默认的最后一个404中间件,因为最后一个404中间件设置了status code,而一但response body之前已经开始写入时,是不能再改变status code或是request header的,否则会报错。微软的官方文档里要求中间件的使用要遵循如下规则:如response body改变后就不要再调用下一个中间件,避免下一个中间件对上一个中间件的httpcontext内容的污染。(本文示例为演示目的,未遵循此约定)

run的用法

run方法的实现代码如下

注意:从run方法的实现的代码可以看出,run是不会再执行下一个中间件的,所以第一个中间run方法后面的中间件都不会起作用。所以一般用run时都是放在中间件的最后

map的用法

map其实准确来说不是中间件的用法,而是新开一个“中间件请求路线分支”,在这个“分支”里,可以再用use和run方法来组件一个新的中间件逻辑。

示例如下

如上示例,请求地址当能匹配上/test里,才会启用map里的中间件

Middleware class的用法

Middleware class不需要继承任何类或是接口,但必须有名为Invoke,返回类型为Task,且第一个参数为HttpContext类型的方法。

示例如下

Asp.net core内置中间件的介绍

中间件名称

如何使用及说明

Authentication

App.UseAuthentication,验证当前请求的用户,并设置HttpContext.User,当OAuth callbacks时,会中止执行下一个中间件。放到要用到用户验证的中间件前面

Static File

app.UseStaticFiles(),判断当前请求是否为静态文件,如果是则中止执行下一个中间件,否则继续下一个中间件。放到管道的最前

Response Caching

app.UseResponseCaching(),缓存中间件

MVC

app.UseMvc(),将MVC引入到中间件管道,如果请求的地址能找到对应的MVC路由,则中止执行下一个中间件。放到管道的最后。

Exception

app.UseDeveloperExceptionPage();或app.UseExceptionHandler();用于处理程序的异常信息。放到管道的最前

Authorization

授权中间件。不需直接引用,App.UseMvc()会在内部调用,并配合app.UseAuthentication()一起使用。

中间件的总结

1、通过use,run,map,middleware class四种方法使用

2、使用多个中间件时,需注意中间件的顺序

3、在设计中间件时,请遵循“责任分离”原则,即一个中间件只对“单一责任”进行处理,如验证用户、授权等。

4、如果对response body做了修改后,请不要再执行下一个中间件

Asp.net core中间件实现原理及用法解说的更多相关文章

  1. asp.net core中间件工作原理

    不少刚学习.net core朋友对中间件的概念一直分不清楚,到底StartUp下的Configure方法是在做什么? public void Configure(IApplicationBuilder ...

  2. ASP.NET Core 中间件基本用法

    ASP.NET Core 中间件 ASP.NET Core的处理流程是一个管道,而中间件是装配到管道中的用于处理请求和响应的组件.中间件按照装配的先后顺序执行,并决定是否进入下一个组件.中间件管道的处 ...

  3. ASP.NET Core中间件实现分布式 Session

    1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件的配置 1.2. 依赖注入中间件 1.3. Cookies ...

  4. 【ASP.NET Core】运行原理之启动WebHost

    ASP.NET Core运行原理之启动WebHost 本节将分析WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build ...

  5. 【ASP.NET Core】运行原理(2):启动WebHost

    本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core ...

  6. 【ASP.NET Core】运行原理(1):创建WebHost

    本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core ...

  7. ASP.NET Core中间件实现分布式 Session(转载)

    ASP.NET Core中间件实现分布式 Session 1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件 ...

  8. ASP.NET Core 中间件自定义全局异常处理

    目录 背景 ASP.NET Core过滤器(Filter) ASP.NET Core 中间件(Middleware) 自定义全局异常处理 .Net Core中使用ExceptionFilter .Ne ...

  9. ASP.NET Core 中间件Diagnostics使用

    ASP.NET Core 中间件(Middleware)Diagnostics使用.对于中间件的介绍可以查看之前的文章ASP.NET Core 开发-中间件(Middleware). Diagnost ...

随机推荐

  1. 【转】nodejs获取post请求发送的formData数据

    前端post请求发送formData的类型数据时,需要服务端引入中间件body-parser,主要原因是post请求发送的数据,是在http的body里面,所以需要进行解析,否则获取不到数据(数据为空 ...

  2. Angular 中的生命周期函数

    一. Angular中的生命周期函数 官方文档:https://www.angular.cn/guide/lifecycle-hooks 生命周期函数通俗的讲就是组件创建.组件更新.组件销毁的时候会触 ...

  3. Linux 验证当前 Video0 不否是v4l设备 linux v4l 编程(1) Video 4 Linux 简介

    #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/types.h ...

  4. 017-mac下project

    下载安装使用 http://www.3322.cc/soft/35716.html

  5. java导入excel很完美的取值的方法

    java导入excel很完美的取值的方法   1.解决方法: /**    * 获取单元格数据内容为字符串类型的数据    * @param cell Excel单元格    * @return St ...

  6. (1) Java实现JDBC连接及事务的方式

    许多数据库的auto-commit默认是ON的,比如MySQL,PostgresSQL等.当然也有默认是OFF的,比如Oracle(Oracle里面执行DML语句是需要手动commit的). 这里我们 ...

  7. react 表单组件 异步渲染,值不会生效,需要手动改变对应组件的显示值

    楼主遇到这个问题已经是第二次,上次我们项目经理给帮忙解决了一次,这次又遇到了,刚开始不知道是这个问题,上次做的笔记也没找到了,估计又忘记了,这里抽三分钟记录一下, 当然这里这样做有个前提:就是你已经和 ...

  8. ELK之elasticsearch插件导致filebeat没有上传日志至elasticsearch解决办法

    使用filebeat收集nginx发现日志为上传,elasticsearch没有日志,kibana没有展示 查看filebeat日志 日志目录为/var/log/filebeat  下面有多个日志文件 ...

  9. iOS摄像头和相册(转)

    iOS摄像头和相册iOS 获取图片有三种方法1. 直接调用摄像头拍照 2. 从相册中选择 3. 从图库中选择 UIImagePickerController 是系统提供的用来获取图片和视频的接口: 用 ...

  10. 修改NGUI 3.11 的控件 inputfileld hide input 属性bug

    1.勾选hideinput属性后,输入中文,会出现,无法显示的问题. 2.勾选hideinput属性后,密码框会出现第一个字母被吃掉的问题 解决方案:控件都不要勾选hideinput属性,代码做如下修 ...