首页 > 其他分享 >.Net6.0中间件

.Net6.0中间件

时间:2022-09-21 21:58:01浏览次数:85  
标签:基于 DI 中间件 Filter 参数 Net6.0 构造函数

中间件基础:

在.net6.0在请求在响应给请求者之前会通过请求管道再处理服务端的逻辑然后再响应给请求者,而请求管道则是由一系列中间件组成的有点类似于过滤器,为了更直观的了解,我们请看下图:

 它可以决定是否将请求传递给请求管道中下一个中间件,也可以处理下一个中间件之前的逻辑也可以处理下一个中间件之后的逻辑.

此为中间件的注册是有顺序的,在定义时一定要注意.

中间件与过滤器的区别:

Filter是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。具体你可以去查找一下关于ASP.NET CORE Filter的相关文章

根据描述,可以看出中间件和过滤器的功能类似,那么他们有什么区别?为什么又要搞一个中间件呢?其实,过滤器和中间件他们的关注点是不一样的,也就是说职责不一样,干的事情就不一样。

同作为两个AOP利器,Filter(过滤器)更贴合业务,它关注于应用程序本身,比如你看ActionFilter 和 ResultFilter,它都直接和你的Action,ActionResult交互了,是不是离你很近的感觉,那我有一些比如对我的输出结果进行格式化,对我的请求的ViewModel进行数据验证啦,肯定就是用Filter无疑了。它是MVC的一部分,它可以拦截到你Action上下文的一些信息,而中间件是没有这个能力的。

可以看到,每一个中间件都都可以在请求之前和之后进行操作。请求处理完成之后传递给下一个请求

使用场景:

那么,何时使用中间件呢?我的理解是在我们的应用程序当中和业务关系不大的一些需要在管道中做的事情可以使用,比如身份验证,Session存储,日志记录等。其实我们的 Asp.net core项目中本身已经包含了很多个中间件。比如 身份认证中间件 UseAuthorization()等系列

中间件管道:

Run: Run称为终端中间件,也就是说该中间件就是管道的末尾,该中间件注册之后,后面的中间件将不再执行,基本上放在末尾就行了,如下图:

 Use:通过该方法可以快速注册一个匿名中间件,如下图:

 需要注意的是:

1.如果要将请求发送给管道中下一个中间件时,一定记得调用next(),否则会导致管道短路,后面的中间件不再被执行

2.在中间件中如有respance的操作,千万不要调用next(),也不要对respanse进行任何更改,否则会抛出异常.

UseWhen:

该方法可以针对不同逻辑创建管道分支,拥有子级中间件,,支持嵌套,其实这里和if else 同理,如下图:

 最后输出:

UseWhen:Use
Use
Run

Map: 

针对不同请求路径创建管道分支,需要注意的是:一旦进入管道分支则不再回到主管道,如下图:

当你访问 /get/user 时,输出如下:

Map get: Use
Request Path: /user
Request PathBase: /get
Map get: Run

当你访问 /post/user/student/1 时,则只会进入下面的map 分支 其他不进入,具体场景交给你们自己尝试哦

MapWhen:

与map类似,也是一旦进入分支则不会再回到主管道,只不过MapWhen不是基于路径而是基于条件,也支持嵌套如下图:

 当你访问 /get/user 时,输出如下:

MapWhen get user: Use

基于约定的中间件:

"约定大于配置",有以下几点:

1.拥有public构造函数,且该构造函数中至少包含一个类型为RequestDeleGet的参数

2.拥有名为Invoke或InvokeAsync的public方法,该方法必须包含类型为HttpContext 的参数,且该参数必须位于第一个位置,另外返回值必须为Task类型

3.在构造函数中的其他参数可以通过依赖注入(DI)填充,也可以通过UseMiddleware进行传参填充

,通过DI填充时,只能接收 Transient 和 Singleton 的DI参数。这是由于中间件是在应用启动时构造的(而不是按请求构造),所以当出现 Scoped 参数时,构造函数内的DI参数生命周期与其他不共享,如果想要共享,则必须将Scoped DI参数添加到Invoke/InvokeAsync来进行使用。通过UseMiddleware传参时,构造函数内的DI参数和非DI参数顺序没有要求,传入UseMiddleware内的参数顺序也没有要求,但是我建议将非DI参数放到前面,DI参数放到后面。(这一块感觉微软做的好牛皮)Invoke/InvokeAsync的其他参数也能够通过依赖注入(DI)填充,可以接收 Transient、Scoped 和 Singleton 的DI参数。

示例如下:

 然后,可以通过UseMiddleware方法将其添加到管道中

 基于工厂的中间件:

优势:

1.上面基于约定的中间件是单例的,但是基于工厂的中间件,可以再依赖注入时设置中间件实例生命周期.

2.使中间件强化了类型,因为实现了IMiddleware接口

该方式的实现基于IMiddlewareFactoryIMiddleware。先来看一下接口定义:

 你有没有想过当我们调用UseMiddleware时,它是如何工作的,事实上UseMiddleware扩展方法会先检查中间件是否实现了IMiddleware接口。

如果实现了,则使用容器中注册的IMiddlewareFactory实例来解析IMiddleware的实例("这下你应该知道为什么称为工厂中间件了吧"),如果没实现

则使用基于约定的中间件逻辑来激活

注意,基于工厂的中间件,在应用的服务容器中一般注册为 Scoped 或 Transient 服务

这样的话,咱们就可以放心的将 Scoped 服务注入到中间件的构造函数中了。

接下来,咱们就来实现一个基于工厂的中间件:

 接下来,注入服务并注册使用中间件:

基于约定的中间件 VS 基于工厂的中间件

  • 基于约定的中间件实例都是 Singleton;而基于工厂的中间件实例可以是 Singleton、Scoped 和 Transient(当然,不建议注册为 Singleton)
  • 基于约定的中间件实例构造函数中可以通过依赖注入传参,也可以用过UseMiddleware传参;而基于工厂的中间件只能通过依赖注入传参
  • 基于约定的中间件实例可以在Invoke/InvokeAsync中添加更多的依赖注入参数;而基于工厂的中间件只能按照IMiddleware的接口定义进行实现。

 

标签:基于,DI,中间件,Filter,参数,Net6.0,构造函数
From: https://www.cnblogs.com/shenweif/p/16717222.html

相关文章

  • 中间件
    简述.netcore中间件?A:中间件是在管道中处理请求的组件,处理完后可以传递给下一个组件。通过在Startup类的Configure方法中使用Use来使用中间件并可以调整顺序。.NETCORE中......
  • 咏南数字化中间件助力工业企业数字化转型
    咏南数字化中间件助力工业企业数字化转型。支持跨平台:LINUX,WINDOWS;支持二种数据库引擎UNIDAC,FIREDAC;支持mormot,crosssocket,diocp,brook,rtc通讯;支持RESTFULAPI和......
  • [基础] BS/CS 区别 Http/Https 区别 中间件请求
    BS和CS的区别:   1、BS结构:Browser-Server-从浏览器到服务器,浏览器打开的所有内容都属于BS(三大主流浏览器Safari、Chrome和Firefo)   2、CS结构:Clinet-Server-Windo......
  • express 中间件
    constexpress=require('express');constapp=express();//定义中间件函数constmw=function(req,res,next){console.log('简单的中间件函数');......
  • 消息中间件
    用途异步处理比如某个调用链的业务逻辑可以分为关键和非关键,那么关键步骤执行完就能立即返回响应,非关键步骤可以放入MQ异步地消费在业务高峰期,可以用k8s动态增......
  • 国产化金蝶中间件
    新建域   按提示一步步执行,比较长我就不细说了。启动域新建完域之后,进入这个域的bin目录,前台启动(第一次先前台启动,要输入管理员初始化密码)前台启动命令:./starta......
  • ASP.NET Core 实战-3.使用中间件管道处理请求
    我们将首先了解中间件的概念,您可以使用它实现的所有事情,以及中间件组件通常如何映射到“横切关注点”。这些是跨越多个不同层的应用程序的功能.日志记录、错误处理和安全......
  • 3.2 Express中间件的初体验
    1.定义中间件函数constexpress=require('express');constapp=express();constmw=function(req,res,next){console.log('这是最简单的中间件函数');......
  • 使用golang实现Redis中间件
    (一).RESP协议解释  RESP协议在Redis1.2被引入,直到Redis2.0才成为和Redis服务器通信的标准。这个协议需要在你的Redis客户端实现。RESP是一个支持多种数据类型的序列化协......
  • day7 rabbit MQ中间件
    中间件屏蔽操作系统复杂性开发人员要熟悉TCPIP底层协议。负载均衡集群,runtimegetimeprocessor线程休眠用waitwaitobjectsleep是thread锁的释放sleep......