.NetCore 请求WebAPI响应信息记录到数据库

环境:.NetCore3.1、VS2019、Web API模板、SqlSugar、MSSqlServer

思路:我们要把每次HTTP请求响应的信息都保存到数据库,因为每次HTTP都会走一遍中间件,我们可以把写入数据库的操作写在自定义中间件上。但是它做的事情比较多,后续也可能变更需求,所有我决定把这个事情写在自定义服务上,让中间件注入该服务进行写入数据库操作。

1.新建服务对应的接口。

public interface IApiLogService
    {
        void DataSave(HttpContext context, long responseTime);
    }

2.新建服务。

2.1.需要安装Nuget包sqlSugarCore,当然也可以使用其他ORM,本例只支持单例模式连接数据库的ORM。

2.2.添加数据库连接。需要在此数据库连接字符串上的服务器地址新建数据库,本人使用本地的SqlServer。

services.AddSingleton(new SqlSugarClient(new ConnectionConfig
            {
                ConnectionString = "server=.;uid=sa;pwd=sasa;database=apilogdemo;MultipleActiveResultSets=true",//必填, 数据库连接字符串
                DbType = DbType.SqlServer,         //必填, 数据库类型
                IsAutoCloseConnection = true,       //默认false, 时候知道关闭数据库连接, 设置为true无需使用using或者Close操作
                InitKeyType = InitKeyType.SystemTable    //默认SystemTable, 字段信息读取, 如:该属性是不是主键,是不是标识列等等信息
            }));

public class ApiLogService : IApiLogService
    {
        private readonly IConfiguration _configuration;
        private readonly SqlSugarClient _dbContext;

        public ApiLogService(IConfiguration configuration, SqlSugarClient dbContext)
        {
            _configuration = configuration;
            _dbContext = dbContext;
        }

        public void DataSave(HttpContext context, long responseTime)
        {
            var isLog = _configuration.GetValue<bool>("ApiLog:IsEnable");
            if (isLog)
            {
                var requestMethod = context.Request.Method;
                var requestURL = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.Path}";
                //var accessToken = context.GetTokenAsync("access_token").Result;//添加身份验证的项目可以使用此方法获取到access_toekn
                var accessToken = string.Empty;
                var requestBody = string.Empty;
                if (requestMethod == "POST")
                {
                    context.Request.Body.Seek(0, SeekOrigin.Begin);
                    var _reader = new StreamReader(context.Request.Body);
                    requestBody = _reader.ReadToEnd();
                }
                _dbContext.Insertable(new ApiLog
                {
                    AccessToken = accessToken,
                    AccessTime = DateTime.Now,
                    AccessAction = requestMethod,
                    AccessApiUrl = requestURL,
                    QueryString = context.Request.QueryString.ToString(),
                    Body = requestBody,
                    HttpStatus = context.Response.StatusCode,
                    ClientIP = context.Connection.RemoteIpAddress.ToString(),
                    ResponseTime = responseTime
                }).ExecuteCommand();
            }
        }
    }

2.3.需要在appsettion.json/appsetting.Development.json文件添加配置信息,用于控制是否启用响应日志,当然也可以不控制。

"ApiLog": {
    "IsEnable": true
  }

2.4.添加响应日志实体,需要在数据库上添加该表。

/// <summary>
    /// 接口请求日志
    /// </summary>
    public class ApiLog
    {
        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:False
        /// </summary>           
        public int ALgID { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string ClientIP { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:False
        /// </summary>           
        public long ResponseTime { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string AccessToken { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:False
        /// </summary>           
        public DateTime AccessTime { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string AccessApiUrl { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string AccessAction { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string QueryString { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string Body { get; set; }

        /// <summary>
        /// Desc:
        /// Default:
        /// Nullable:False
        /// </summary>           
        public int HttpStatus { get; set; }
    }

3.此时,我们的服务已经定义好了。接下来是自定义一个中间件。

3.1.新建中间件,注入并使用刚才定义好的服务。

public class LogMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IApiLogService _apiLogService;
        private readonly IConfiguration _configration;

        public LogMiddleware(RequestDelegate next, IApiLogService apiLogService, IConfiguration configration)
        {
            _next = next;
            _apiLogService = apiLogService;
            _configration = configration;
        }

        public Task Invoke(HttpContext context)
        {
            var watch = new Stopwatch();
            watch.Start();
            context.Response.OnStarting(() =>
            {
                var isLog = _configration.GetValue<bool>("ApiLog:IsEnable");
                if (isLog)
                {
                    watch.Stop();
                    _apiLogService.DataSave(context, watch.ElapsedMilliseconds);
                }
                return Task.CompletedTask;
            });
            
            return this._next(context);
        }
    }

 3.2.新建暴露中间件扩展类。

public static class LogMiddlewareExtension
    {
        public static IApplicationBuilder UseLogMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<LogMiddleware>();
        }
    }

4.我们的工作已经做好了,接下来使用自定义的中间件就可以了。

4.1.添加自定义服务

services.AddSingleton<IApiLogService, ApiLogService>();

 4.2.使用自定义中间件。

app.UseLogMiddleware();

 5.运行项目,查看效果。

 源码地址:https://github.com/Jcanc/WebApiResponseLog

 写得不好,请温柔的喷。

猜你喜欢

转载自www.cnblogs.com/resplendent/p/12677942.html