Asp.net core使用中间件实现控制器操作日志功能

前序

需要实现一个控制器操作日志的功能并且可以局部使用,参考java拦截器spring aop注解;原先考虑使用操作过滤器、但是操作过滤器包裹范围没有异常过滤器的范围大,抛出异常后就不执行了。然后考虑使用中间件,使用中间件存在一个问题;中间件没有局部使用的功能。采用特性去标记控制器,在中间件中获取到控制器上标记的特性存在标记就执行,没有标记跳过日志记录逻辑。

实现思路:

  1. 自定义特性;
  2. 在每个控制器方法上加上自定义特性;
  3. 通过中间件,在每个控制器方法执行完后,获取该特性信息,写入数据库;

注意 : 有坑的地方,在中间件获取控制器的特性,获取控制器(端点)一直为 null 这是根据程序配置入口使用顺序相关。

问题

program.cs
在这里插入图片描述
这是官方文档的说明
在这里插入图片描述
官方文档地址

代码

特性 LoggingAttribute
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class LoggingAttribute : Attribute
{

    public string name;

    public LoggingAttribute(string s)
    {
        this.name = s;
    }

}
全局异常拦截 GlobalExceptionFilter
public class GlobalExceptionFilter : IAsyncExceptionFilter
{
    private readonly ILogger<GlobalExceptionFilter> _logger;

    public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
    {
        _logger = logger;
    }

    public Task OnExceptionAsync(ExceptionContext context)
    {
        switch (context.Exception)
        {           
            default:
                context.Result = new ObjectResult("500");
                _logger.LogError(context.Exception.Message);
                break;
        }
        context.ExceptionHandled = true;
        return Task.CompletedTask;
    }
}
日志中间 LogMiddleware
public class LogMiddleware
{
    private readonly RequestDelegate _next;

    public LogMiddleware(RequestDelegate next)
    {
        this._next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        Debug.WriteLine("----------入口----");
        // todo 这里获取端点根据程序启动入口配置顺序有关,未配置和否则端点一直为null,踩了一天的坑官网有解释
        var log = context.GetEndpoint()?.Metadata.GetMetadata<LoggingAttribute>();
        if (log == null)
        {
            await _next(context);
            return;
        }
        // todo 保存起始日志
        await _next(context);
        // todo 执行完成日志
        Debug.WriteLine("----------出口----");
    }
    
}
测试控制器 TestController
[ApiController]
[Route("[controller]/[action]")]
public class TestController  : ControllerBase
{
    [HttpGet]
    public string get()
    {
        return "100";
    }
    
    [Logging("测试接口")]
    [HttpGet]
    public string get1()
    {
        throw new Exception("200");
        return "100";
    }   
}
程序入口 Program
var builder = WebApplication.CreateBuilder(args);

/*builder.Services.Configure<MongodbSettings>(
    builder.Configuration.GetSection("BookStoreDatabase"));*/

// 注册筛选器
builder.Services.Configure<MvcOptions>(opt =>
{
    opt.Filters.Add<GlobalExceptionFilter>();
});
builder.Services.AddControllers();

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();

app.UseRouting();
app.MapControllers();
// 注意:使用顺序
app.UseMiddleware<LogMiddleware>();
app.UseEndpoints(e => e.MapControllers());  

app.Run();

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值