博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET Core开发实战(第21课:中间件:掌控请求处理过程的关键)--学习笔记(下)...
阅读量:4031 次
发布时间:2019-05-24

本文共 3380 字,大约阅读时间需要 11 分钟。

21 | 中间件:掌控请求处理过程的关键

如果在 Map 的时候逻辑复杂一点,不仅仅判断它的 URL 地址,而且要做特殊的判断的话,可以这么做把判断逻辑变成一个委托

我们要判断当我们的请求地址包含 abc 的时候,输出 new abc

app.MapWhen(context =>{    return context.Request.Query.Keys.Contains("abc");}, builder =>{    builder.Run(async context =>    {        await context.Response.WriteAsync("new abc");    });});

启动程序,没有任何输出

当我们在默认启动地址后面输入 ?abc=1 的时候,可以看到输出了 new abc

这里用到了一个 Run 的方法,上一节用到的是 Use 方法

app.Map("/abc", abcBuilder =>{    abcBuilder.Use(async (context, next) =>    {        //await context.Response.WriteAsync("Hello");        await next();        await context.Response.WriteAsync("Hello2");    });});

Run 和 Use 的区别是什么呢?

Use 是指我们可以像注册一个完整的中间件一样,将 next 注入进来,我们可以去决定是否执行后续的中间件

Run 的含义就表示我们这里就是中间件执行的末端,也就不在执行后面的中间件了,在这里将返回请求

那我们如何像 UseRouting UseEndpoints 一样来设计我们自己的中间件呢?

这里定义好了一个 MyMiddleware

namespace MiddlewareDemo.Middlewares{    class MyMiddleware    {        RequestDelegate _next;        ILogger _logger;        public MyMiddleware(RequestDelegate next, ILogger
logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { using (_logger.BeginScope("TraceIdentifier:{TraceIdentifier}", context.TraceIdentifier)) { _logger.LogDebug("开始执行"); await _next(context); _logger.LogDebug("执行结束"); } } }}

定义中间件是用了一个约定的方式,中间件的类包含一个方法 Invoke 或者 InvokeAsync 这样一个方法,它的返回是一个 Task,入参是一个 HttpContext,实际上可以理解成与中间件的委托是一样的,只要我们的类包含这样一个方法,就可以把它作为一个中间件注册进去,并被框架识别到

这里还定义了一个 MyBuilderExtensions

namespace Microsoft.AspNetCore.Builder{    public static class MyBuilderExtensions    {        public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder app)        {            return app.UseMiddleware
(); } }}

把我们的中间件注册进去,这个方法就是 UseMyMiddleware

通过这样的定义,我们就可以使用自己的中间件

app.UseMyMiddleware();

启动程序,输出如下:

控制台输出

dbug: MiddlewareDemo.Middlewares.MyMiddleware[0]      => RequestPath:/weatherforecast RequestId:0HLU50UEM3M9F:00000001, SpanId:|77f92fe8-4a6d800968327989., TraceId:77f92fe8-4a6d800968327989, ParentId: => TraceIdentifier:0HLU50UEM3M9F:00000001      开始执行dbug: MiddlewareDemo.Middlewares.MyMiddleware[0]      => RequestPath:/weatherforecast RequestId:0HLU50UEM3M9F:00000001, SpanId:|77f92fe8-4a6d800968327989., TraceId:77f92fe8-4a6d800968327989, ParentId: => TraceIdentifier:0HLU50UEM3M9F:00000001      执行结束

网页控制器输出

[{"date":"2020-03-11T23:30:55.3411696+08:00","temperatureC":20,"temperatureF":67,"summary":"Warm"},{"date":"2020-03-12T23:30:55.3417863+08:00","temperatureC":52,"temperatureF":125,"summary":"Bracing"},{"date":"2020-03-13T23:30:55.3417916+08:00","temperatureC":-3,"temperatureF":27,"summary":"Mild"},{"date":"2020-03-14T23:30:55.341792+08:00","temperatureC":35,"temperatureF":94,"summary":"Balmy"},{"date":"2020-03-15T23:30:55.3417923+08:00","temperatureC":37,"temperatureF":98,"summary":"Sweltering"}]Hello2

如果要实现一个断路器,就是不执行后续逻辑,注释掉一行

_logger.LogDebug("开始执行");//await _next(context);_logger.LogDebug("执行结束");

启动程序,页面不会输出任何内容,只会在控制台打印出中间件的执行过程,后续的控制器不会执行

这样就实现了一个断路器,也就意味着可以使用自己的中间件做请求的控制,而且时非常灵活的控制

在使用中间件的过程中,需要非常注意的是注册中间件的顺序,这些顺序就决定了中间件执行的时机,某些中间件会是断路器的作用,某些中间件会做一些请求内容的处理

还有一个比较关键的要点是指应用程序一旦开始向 Response write 的时候,后续的中间件就不能再去操作它的 header,这一点是需要注意的

可以通过 Context.Response.HasStarted 来判断是否已经开始向响应的 body 输出内容,一旦输出了内容,就不要再操作 header

转载地址:http://xcwdi.baihongyu.com/

你可能感兴趣的文章
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>
Ubuntu 13.10使用fcitx输入法
查看>>
pidgin-lwqq 安装
查看>>
mint/ubuntu安装搜狗输入法
查看>>
C++动态申请数组和参数传递问题
查看>>
opencv学习——在MFC中读取和显示图像
查看>>
retext出现Could not parse file contents, check if you have the necessary module installed解决方案
查看>>
pyQt不同窗体间的值传递(一)——对话框关闭时返回值给主窗口
查看>>
linux mint下使用外部SMTP(如网易yeah.net)发邮件
查看>>
北京联通华为光猫HG8346R破解改桥接
查看>>
python使用win32*模块模拟人工操作——城通网盘下载器(一)
查看>>
python append 与浅拷贝
查看>>
Matlab与CUDA C的混合编程配置出现的问题及解决方案
查看>>
python自动化工具之pywinauto(零)
查看>>