Skip to content

dotnetcore 中间件 #42

@Henrik-Xu

Description

@Henrik-Xu

中间件

中间的原理

总结:通过断点调试中间件的执行,我们发现中间件确实是按照顺序执行的。我们通过堆栈已经观察到。

思考:一个中间件内部究竟执行了什么?

中间件使用的需要的组件:

1、扩展类 (DeveloperExceptionPageExtensions)

2、中间件类(DeveloperExceptionPageMiddleware)

中间件是按照从上往下的顺序执行的。

分析:当中间件被执行的时候,会加到 _Components 集合,然后通过 Build 方法反转,实现了按顺序执行。

这个中间件是放到所有中间件的第一个位置上面。

AspNetCore 请求处理流程

Pipleline 请求管道底层机制结构

系统中间件的使用

实现一个欢迎页面:

  1. Nuget 引入包 Microsoft.AspNetCore.Diagnostics

  2. Configure 方法中添加中间件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDefaultFiles(); //启动后的默认页面

    app.UseStaticFiles();
    app.UseRouting();

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

结论:

  1. 中间件的顺序添加十分重要

  2. UseDefaultFiles() 这个扩展方法,其实是重写了 URL,并没有提供真正的文件。

所以,必须开启UseStaticFiles

默认页面的使用是有顺序要求的。

default.htm
default.html

index.htm
index.html

自定义中间件

实现一个获取 URL 地址的中间件

  1. 扩展类和扩展方法
/// <summary>
/// 中间件对应的扩展类
/// </summary>
public static class MyRequestIPExtensions
{
    public static IApplicationBuilder UseMyRequestIP(this IApplicationBuilder app)
    {
        if (app == null)
        {
            throw new ArgumentNullException("app");
        }
        return app.UseMiddleware<MyRequestIPMiddleware>(Array.Empty<object>());
    }
}
  1. 中间件类
/// <summary>
/// 中间件类
/// </summary>
public class MyRequestIPMiddleware
{
    //【1】定义委托属性和日志属性
    private readonly RequestDelegate _next;

    private readonly ILogger _logger;

    /// <summary>
    /// 【2】通过构造方法注入
    /// </summary>
    /// <param name="next"></param>
    /// <param name="loggerFactory"></param>
    public MyRequestIPMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
    {
        this._next = next;
        this._logger = loggerFactory.CreateLogger<MyRequestIPMiddleware>();        
    }

    /// <summary>
    /// 【3】添加Invoke方法
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task Invoke(HttpContext context)
    {
        _logger.LogInformation("当前用户的IP地址:" + context.Connection.RemoteIpAddress.ToString());

        await _next.Invoke(context); //传递到下一个中间件
    }
}
  1. 添加中间件
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseStaticFiles();
    app.UseRouting();

    app.UseMyRequestIP();

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions