zoukankan      html  css  js  c++  java
  • Asp.NetCore 自定义中间件

    这节演示一下自定义中间件,第一节我们讲到,中间件的处理流程就像一个俄罗斯套娃,那这种俄罗斯套娃型的流程内部是如何实现的呢,下面请看代码​。

        ​第一种写法是直接写在Configure方法中的,使用app.Use(委托)配合lambda表达式使用,适合很轻量级的中间件。​

    app.Use(async (context, next) =>
      {
          await context.Response.WriteAsync("CustomerMiddleWare1-in
    ");
          await next();
          await context.Response.WriteAsync("CustomerMiddleWare1-out");
      });

    ​微软约定中间件需要两个参数,一个是httpcontext上下文对象,一个是Task类型的委托​。通过上下文对象,处理请求,通过委托​传递上下文对象到下一个中间件(这也是套娃模式的由来)。

        ​这也限制了方法,必须是异步的async方法,调用next()之后,上下文对象发送给下一中间件了,该方法就会处于等待状态,直到后续的中间件处理完毕,返回后,再执行next()方法之后的代码​。(关于同步和异步的有关知识,将在后续进行讲解)

        ​除了使用Use()方法,还有一种用法,这个方法有点特殊,因为它不存在next()方法传递上下文对象,它是请求管道的底,用于直接返回响应

    //run 是终端中间件,他是没有next()方法的,只要进入这个中间件,后续的中间件都不会执行了,从它这里请求完毕原路返回 
     app.Run(async context =>
     {
          await context.Response.WriteAsync("I am End MiddleWare
    ");
     });

     ​.NetCore 3.x推出了一个新的中间件,叫EndPoints

    app.UseEndpoints(endpoints =>
     {
            endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
     });

      ​它跟Run()一样,是兜底的中间件,但是用法比较特殊了,微软给我们的默认配置就是直接路由到某一页面,一般是网站首页​。

     下面看一下运行结果的演示,有如下三个中间件:

     //use是添加中间中间件,就是处理完了,继续传给下一个中间件,它有next()委托
     app.Use(async (context, next) =>
     {
       await context.Response.WriteAsync("CustomerMiddleWare1-in
    ");
       await next();
       await context.Response.WriteAsync("CustomerMiddleWare1-out");
     });
     app.Use(async (context, next) =>
     {
       await context.Response.WriteAsync("CustomerMiddleWare2-in
    ");
       await next();
       await context.Response.WriteAsync("CustomerMiddleWare2-out
    ");
     });
    //run 是终端中间件,他是没有next()方法的,只要进入这个中间件,后续的中间件都不会执行了,从它这里请求完毕原路返回 
     app.Run(async context =>
     {
       await context.Response.WriteAsync("I am End MiddleWare
    ");
     });

    运行结果为:

      这很直观的反应了中间件的顺序执行,以及嵌套执行

     下面看一下如何定义一个真正的自定义中间件

        首先,我们要明确,微软规定的自定义中间件的要求

            1.具有类型为RequestDelegate参数的公共构造函数,这个参数就是请求委托,它在一个个的中间件中传递

             2.具有Invoke或者InvokeAsync的方法,该方法的返回值必须是Task,而且第一个参数必须是HttpContext

     public class MyMiddleWare
        {
            private readonly RequestDelegate _next;
    
            public MyMiddleWare( RequestDelegate next )
            {
                _next = next;
            }
    
            public async Task InvokeAsync(HttpContext context)
            {
                //此处写中间件业务逻辑
                //然后调用next指向下一个中间件
                //调用next之前,属于请求部分的处理
                await _next(context);
                //next执行完毕之后,属于相应部分的处理
            }
        }

       ​定义完成以后,使用UseMiddleware<中间件>()将自定义中间件添加进来

    app.UseMiddleware<MyMiddleWare>();

     ​但这样的用法,还是少了一点优雅与灵活性,我们可以通过扩展方法的形式,为IApplicationBuilder添加扩展方法,实现自定义中间件添加与配置的灵活应用(扩展方法在之前的文章中有讲)​

    public static class MyMiddleWareExtension
        {
            public static IApplicationBuilder UseMymiddleware(this IApplicationBuilder app)
            {
                return app.UseMiddleware<MyMiddleWare>();
            }
        }

    这样的话,就可以直接调用方法添加中间件了

     //使用扩展方法的形式,添加自定义中间件然后可以通过构造方法的形式,传递配置参数
     app.UseMymiddleware();

     初学者可对此做初步了解,对其中设计的代码语法知识,是必须要掌握的。另外,如果需要查看ASP.NetCore的源码,请访问https://github.com/dotnet/aspnetcore自行下载或克隆到本地

     这是我公众号二维码,最新的文章会同步至此

  • 相关阅读:
    JavaScript cookie详解
    Javascript数组的排序:sort()方法和reverse()方法
    javascript中write( ) 和 writeln( )的区别
    div做表格
    JS 盒模型 scrollLeft, scrollWidth, clientWidth, offsetWidth 详解
    Job for phpfpm.service failed because the control process exited with error code. See "systemctl status phpfpm.service" and "journalctl xe" for details.
    orm查询存在价格为空问题
    利用救援模式破解系统密码
    SSH服务拒绝了密码
    C# 调用 C++ DLL 中的委托,引发“对XXX::Invoke类型的已垃圾回收委托进行了回调”错误的解决办法
  • 原文地址:https://www.cnblogs.com/charlesmvp/p/13279226.html
Copyright © 2011-2022 走看看