.NetCore 3.1 使用中间件实现AOP

什么是AOP?

通常我们再进行系统开发的时候,不可避免的需要对一些接口进行请求记录,执行时间记录,返回结果记录等等。

当然作为开发了几年的老油条,大家对于重复性的工作都是很不屑去做的,其实是懒,嘎嘎

那么这时候就要引入AOP的概念了,相信有一两年开发经验的同学对AOP都不会陌生,这里对其概念不再赘述,

简而言之就是牛逼的可以在函数执行前和执行后做各种操作的好东西。

 

什么是中间件?

官方解释:

中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在管道中的下一个组件前后执行工作。

请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。

 

区别?

因AOP无法作用于webapi 的Controller,这里就只讨论中间件的实现。

 

如何实现中间件?

不说废话,直接上代码。

 

中间件定义:

public class AopMiddleware
{
    private readonly RequestDelegate _next;
    public AopMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {

        //执行Action
        await _next(context);

    }
}

 

在 Startup 的 Configure 增加触发点:

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

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseCors();
    app.UseAuthorization();
 
    //这就是咱自定义的中间件了,注意位置要在UserEndpoints之前
    app.UseMiddleware<AopMiddleware>();
 
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

 

以上就是中间件的基本框架,可以在 执行Action 前后进行肆意的操作。

 

 

如何实现入参抓取和出参捕获?

public async Task InvokeAsync(HttpContext context)
{
    HttpRequest request = context.Request;
    // 获取请求body内容
    if (request.Method.ToLower().Equals("post"))
    {
        // Ensure the request Microsoft.AspNetCore.Http.HttpRequest.Body can be read multiple times
        request.EnableBuffering();

        //获取到body值
        string body = await new StreamReader(request.Body).ReadToEndAsync();

        //必须有,不然后续Action 执行会出现 A non-empty request body is required. 的异常
        request.Body.Position = 0;
    }
    else if (request.Method.ToLower().Equals("get"))
    {
        string param = request.QueryString.Value;
    }

    //获取到Response.body内容
    using (var ms = new MemoryStream())
    {
        var orgBodyStream = context.Response.Body;
        context.Response.Body = ms;

        //执行controller中正常逻辑代码
        await _next(context);

        using (var sr = new StreamReader(ms))
        {
            ms.Seek(0, SeekOrigin.Begin);
            //得到 Action 执行结果
            var responseJsonResult = sr.ReadToEnd();

            context.Response.Body = orgBodyStream;
            //返回 Action 执行结果 
            await context.Response.WriteAsync(responseJsonResult, Encoding.UTF8);
        }
    }
}
View Code

 

 

以上,如果有什么纰漏或者您有什么好的想法,欢迎留言讨论。

 

posted @ 2021-09-16 17:16  大山楂丸子  阅读(293)  评论(0编辑  收藏  举报