.Net6 Web Core API --- AOP -- log4net 封装 -- MySQL -- txt
目录
一、引入 NuGet 包
二、配置log4net.config
三、编写Log4net封装类
四、编写日志记录类
五、AOP -- 拦截器 -- 封装
六、案例编写
七、结果展示
一、引入 NuGet 包
log4net
Microsoft.Extensions.Logging.Log4Net.AspNetCore
MySql.Data ---- MySQL数据库需要
Newtonsoft.Json
Autofac
Autofac.Extensions.DependencyInjection
Autofac.Extras.DynamicProxy
二、配置log4net.config
注:当前网上有两种 log4net.config 配置文件, 一种是以<log4net>为根目录, 另一种以<configuration> 为根目录
<?xml version="1.0" encoding="utf-8"?><log4net><!--正常日志:::记录正常日志--><!-- appender 定义日志输出方式 将日志以回滚文件的形式写到MySQL数据库中。--><appender name="ADONetAppender" type="log4net.Appender.ADONetAppender"><!-- 代表缓存大小,在没达到缓存大小时,暂时不会存到数据库中, --><!-- 当程序关闭之后,会将未插入的信息加入到数据库中 --><bufferSize value="1" /><!--引入《MySql.Data》包--><param name="ConnectionType" value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" /><!--配置连接数据库的字符串--><param name="ConnectionString" value="server=localhost;database=TTTTT;uid=root;pwd=123456;"/><!--配置MySQL的插入语句--><param name="CommandText" value="insert into log4net(log_datetime,log_thread,log_level,log_logger,log_message) values(@log_datetime, @log_thread , @log_level, @log_logger, @log_message)" /><param name="Parameter"><param name="ParameterName" value="@log_datetime" /><param name="DbType" value="DateTime" /><param name="Layout" type="log4net.Layout.PatternLayout"><param name="ConversionPattern" value="%d{yyyy'-'MM'-'dd HH':'mm':'ss}" /></param></param><param name="Parameter"><param name="ParameterName" value="@log_thread" /><param name="DbType" value="String" /><param name="Size" value="255" /><param name="Layout" type="log4net.Layout.PatternLayout"><param name="ConversionPattern" value="%t" /></param></param><param name="Parameter"><param name="ParameterName" value="@log_level" /><param name="DbType" value="String" /><param name="Size" value="255" /><param name="Layout" type="log4net.Layout.PatternLayout"><param name="ConversionPattern" value="%p" /></param></param><param name="Parameter"><param name="ParameterName" value="@log_logger" /><param name="DbType" value="String" /><param name="Size" value="255" /><param name="Layout" type="log4net.Layout.PatternLayout"><param name="ConversionPattern" value="%c" /></param></param><param name="Parameter"><param name="ParameterName" value="@log_message" /><param name="DbType" value="String" /><param name="Size" value="4000" /><param name="Layout" type="log4net.Layout.PatternLayout"><param name="ConversionPattern" value="%m" /></param></param></appender><!--正常日志:::记录正常日志--><!--按日期分割日志文件 一天一个--><!-- appender 定义日志输出方式 将日志以回滚文件的形式写到文件中。--><appender name="RollingFile" type="log4net.Appender.RollingFileAppender"><!-- 定义中文编码类型 UTF-8--><param name="Encoding" value="utf-8" /><!--定义文件存放位置--><file value="Log\log_"/><!--是否追加到文件--><appendToFile value="true"/><!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全--><lockingModel type="log4net.Appender.FileAppender+MinimalLock"/><!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数--><maxSizeRollBackups value="-1"/><!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])--><rollingStyle value="Composite"/><datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/><!--是否只写到一个文件中--><staticLogFileName value="false"/><!--每个文件的大小。只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志--><maximumFileSize value="100MB"/><!--计数类型为1,2,3…--><!--<param name="CountDirection" value="1"/>--><layout type="log4net.Layout.PatternLayout"><!--输出格式-样例:记录时间:2022-08-24 17:59:31,172 线程ID:[4] 日志级别:INFO 当前类:Log4NetDemo.MainClass 日志描述:创建连接。--><conversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 当前类:%logger %newline日志描述:%message %newline %newline"/></layout></appender><!--错误日志:::记录错误日志--><!--按日期分割日志文件 一天一个--><!-- appender 定义日志输出方式 将日志以回滚文件的形式写到文件中。--><appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"><!-- 定义中文编码类型 UTF-8--><param name="Encoding" value="utf-8" /><!--定义文件存放位置--><file value="Log\error_"/><!--是否追加到文件--><appendToFile value="true"/><!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全--><lockingModel type="log4net.Appender.FileAppender+MinimalLock"/><!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数--><maxSizeRollBackups value="-1"/><!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])--><rollingStyle value="Composite"/><datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/><!--是否只写到一个文件中--><staticLogFileName value="false"/><!--每个文件的大小。只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志--><maximumFileSize value="100MB"/><!-- layout 控制Appender的输出格式,也可以是xml 一个Appender只能是一个layout--><layout type="log4net.Layout.PatternLayout"><!--每条日志末尾的文字说明--><!--输出格式 模板--><!-- <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger 操作者ID:%property{Operator} 操作类型:%property{Action}%n 当前机器名:%property%n当前机器名及登录用户:%username %n 记录位置:%location%n 消息描述:%property{Message}%n 异常:%exception%n 消息:%message%newline%n%n" />--><!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info--><!--<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n错误描述:%message%newline %n"/>--><conversionPattern value="%n==========%n【日志级别】%-5level%n【记录时间】%date%n【执行时间】[%r]毫秒%n【错误位置】%logger 属性[%property{NDC}]%n【错误描述】%message%n【错误详情】%newline"/></layout><filter type="log4net.Filter.LevelRangeFilter,log4net"><levelMin value="ERROR" /><levelMax value="FATAL" /></filter></appender><!--DEBUG:::记录DEBUG日志--><!--按日期分割日志文件 一天一个--><!-- appender 定义日志输出方式 将日志以回滚文件的形式写到文件中。--><appender name="DebugAppender" type="log4net.Appender.RollingFileAppender"><!-- 定义中文编码类型 UTF-8--><param name="Encoding" value="utf-8" /><!--定义文件存放位置--><file value="Log\debug_"/><!--是否追加到文件--><appendToFile value="true"/><!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全--><lockingModel type="log4net.Appender.FileAppender+MinimalLock"/><!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数--><maxSizeRollBackups value="-1"/><!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])--><rollingStyle value="Composite"/><datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/><!--是否只写到一个文件中--><staticLogFileName value="false"/><!--每个文件的大小。只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志--><maximumFileSize value="100MB"/><!-- layout 控制Appender的输出格式,也可以是xml 一个Appender只能是一个layout--><layout type="log4net.Layout.PatternLayout"><!--输出格式-样例:记录时间:2022-08-24 17:59:31,172 线程ID:[4] 日志级别:INFO 当前类:Log4NetDemo.MainClass 日志描述:创建连接。--><conversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 当前类:%logger %newline日志描述:%message %newline %newline"/></layout><filter type="log4net.Filter.LevelRangeFilter,log4net"><levelMin value="DEBUG" /><levelMax value="WARN" /></filter></appender><root><!--日志等级:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL--><level value="ALL" /><appender-ref ref="ADONetAppender" /><appender-ref ref="RollingFile" /><appender-ref ref="ErrorAppender" /><appender-ref ref="DebugAppender" /></root></log4net>
三、编写Log4net封装类
public static class CustomLog4netExt
{public static void AddLog4netExt(this WebApplicationBuilder builder){// 添加 Log4net 配置文件builder.Logging.AddLog4Net("log4net.config");// log错误日志配置builder.Services.AddControllers(options =>{options.SuppressAsyncSuffixInActionNames = false;options.Filters.Add(typeof(GlobalExceptionsFilter));});}
}
四、编写日志记录类
全局报错监测类
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace Log4Test.Log4;/// <summary>
/// 全局异常错误日志
/// </summary>
public class GlobalExceptionsFilter : IExceptionFilter
{private readonly IWebHostEnvironment _env;private readonly ILogger<GlobalExceptionsFilter> _logger;public GlobalExceptionsFilter(IWebHostEnvironment env, ILogger<GlobalExceptionsFilter> logger){_env = env;_logger = logger;}public void OnException(ExceptionContext context){var json = new JsonErrorResponse();json.Message = context.Exception.Message;//错误信息if (_env.IsDevelopment()){json.DevelopmentMessage = context.Exception.StackTrace;//堆栈信息}context.Result = new InternalServerErrorObjectResult(json);//采用log4net 进行错误日志记录_logger.LogError(WriteLog(json.Message, context.Exception));}/// <summary>/// 自定义返回格式/// </summary>/// <param name="throwMsg"></param>/// <param name="ex"></param>/// <returns></returns>public string WriteLog(string throwMsg, Exception ex){return string.Format("【自定义错误】:{0} \r\n" +"【异常类型】:{1} \r\n" +"【异常信息】:{2} \r\n" +"【堆栈调用】:{3}", new object[] { throwMsg,ex.GetType().Name, ex.Message, ex.StackTrace });}}public class InternalServerErrorObjectResult : ObjectResult
{public InternalServerErrorObjectResult(object value) : base(value){StatusCode = StatusCodes.Status500InternalServerError;}
}
//返回错误信息
public class JsonErrorResponse
{/// <summary>/// 生产环境的消息/// </summary>public string Message { get; set; }/// <summary>/// 开发环境的消息/// </summary>public string DevelopmentMessage { get; set; }
}
日常方法监测类
using Castle.DynamicProxy;
using Newtonsoft.Json;namespace LOG.Test;/// <summary>
/// 自定义 方法拦截器
/// </summary>
public class CustomInterceptor : IInterceptor
{private readonly ILogger<CustomInterceptor> _logger;public CustomInterceptor(ILogger<CustomInterceptor> logger){_logger = logger;}public void Intercept(IInvocation invocation){string result = $"开始执行-->\n方法名: {invocation.Method.Name}\n";foreach (var item in invocation.Arguments){result += $"入参---{JsonConvert.SerializeObject(item)}\n";}_logger.LogInformation(result);invocation.Proceed();_logger.LogInformation($"结束执行-->\n方法名: {invocation.Method.Name}\n" +$"返回结果---{JsonConvert.SerializeObject(invocation.ReturnValue)}\n");}
}
五、AOP -- 拦截器 -- 封装
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.DynamicProxy;namespace LOG.Test;public static class CustomAOPExt
{public static void AddAOPExt(this WebApplicationBuilder builder){builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()) // 工厂替换,把Autofac整合进来.ConfigureContainer<ContainerBuilder>(containerBuilder =>{// 依赖注入containerBuilder.RegisterType<CustomInterceptor>(); containerBuilder.RegisterType<Student>().As<IStudent>().EnableClassInterceptors(); // 开启类拦截器 //containerBuilder.RegisterType<Student>().As<IStudent>().EnableInterfaceInterceptors(); // 开启接口拦截器});}
}
六、案例编写
// 在Program.cs 中// 添加 lg4net 扩展
builder.AddLog4netExt();
// 添加 AOP 扩展
builder.AddAOPExt();
创建 Student 和 IStudent 测试类和接口
创建 一个 控制器
七、结果展示
如有错误,烦请批评指正
相关文章:

.Net6 Web Core API --- AOP -- log4net 封装 -- MySQL -- txt
目录 一、引入 NuGet 包 二、配置log4net.config 三、编写Log4net封装类 四、编写日志记录类 五、AOP -- 拦截器 -- 封装 六、案例编写 七、结果展示 一、引入 NuGet 包 log4net Microsoft.Extensions.Logging.Log4Net.AspNetCore MySql.Data ---- MySQL…...

【论文阅读】对抗溯源图主机入侵检测系统的模仿攻击(NDSS-2023)
作者:伊利诺伊大学芝加哥分校-Akul Goyal、Gang Wang、Adam Bates;维克森林大学-Xueyuan Han、 引用:Goyal A, Han X, Wang G, et al. Sometimes, You Aren’t What You Do: Mimicry Attacks against Provenance Graph Host Intrusion Detect…...
微信小程序多图片上传实用代码记录
微信小程序多图片上传实用代码记录 由于在小程序中,wx.uploadFile 只能一次上传一张图片,因此在一次需要上传多张图片的应用场景中例如商品图片上传、评论图片上传等场景下,不得不使用for等循环上传每一张图片,多次调用wx.upload…...
android实现获取系统全局对象实例
无需Context获取系统常用全局对象:Application,Activity,PackageManager等。 import android.app.Activity; import android.app.Application; import android.app.Service; import android.content.Context; import android.content.pm.Pac…...

viewerjs 如何新增下载图片功能(npm包补丁)
文章目录 先实现正常的效果实现下载图片改变viewerjs的build函数源码改变之后,执行npm i 之后node_modules源码又变回了原样 1、viwerjs所有功能都很完善,但唯独缺少了图片的下载 2、需求:在用viwerjs旋转图片后,可以直接下载旋转…...

基于YOLOv7开发构建MSTAR雷达影像目标检测系统
MSTAR(Moving and Stationary Target Acquisition and Recognition)数据集是一个基于合成孔径雷达(Synthetic Aperture Radar,SAR)图像的目标检测和识别数据集。它是针对目标检测、机器学习和模式识别算法的研究和评估…...
关于c++中mutable、const、volatile这三个关键字及对应c++与汇编示例源码
这哥三之间的关系是有趣的,不妨看看这个: cv (const and volatile) type qualifiers - cppreference.com mutable permits modification of the class member declared mutable even if the containing object is declared const. 即便一个对象是con…...

把大模型装进手机,分几步?
点击关注 文 | 姚 悦 编 | 王一粟 大模型“跑”进手机,AI的战火已经从“云端”烧至“移动终端”。 “进入AI时代,华为盘古大模型将会来助力鸿蒙生态。”8月4日,华为常务董事、终端BG CEO、智能汽车解决方案BU CEO 余承东介绍,…...

c++游戏制作指南(三):c++剧情类文字游戏的制作
🍿*★,*:.☆( ̄▽ ̄)/$:*.★* 🍿 🍟欢迎来到静渊隐者的csdn博文,本文是c游戏制作指南的一部🍟 🍕更多文章请点击下方链接🍕 🍨 c游戏制作指南dz…...

Flutter系列文章-实战项目
在本篇文章中,我们将通过一个实际的 Flutter 应用来综合运用最近学到的知识,包括保存到数据库、进行 HTTP 请求等。我们将开发一个简单的天气应用,可以根据用户输入的城市名获取该城市的天气信息,并将用户查询的城市列表保存到本地…...
HCIA---TCP/UDP协议
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 文章目录 一.UDP协议简介 UDP协议的特点: 二.TCP协议简介 TCP协议特点 三.TCP和UDP的区别 思维导图 一.UDP协议简介 UDP(User …...

数据库索引的使用
1、MySQL的基本架构 架构图 左边的client可以看成是客户端,客户端有很多,像我们经常你使用的CMD黑窗口,像我们经常用于学习的WorkBench,像企业经常使用的Navicat工具,它们都是一个客户端。右边的这一大堆都可以看成是…...
校验 GPT-4 真实性的三个经典问题:快速区分 GPT-3.5 与 GPT-4,并提供免费测试网站
现在已经有很多 ChatGPT 的套壳网站,以下分享验明 GPT-4 真身的三个经典问题,帮助你快速区分套壳网站背后到底用的是 GPT-3.5 还是 GPT-4。 大家可以在这个网站测试:https://ai.hxkj.vip,免登录可以问三条,登录之后无限…...
SpringBoot整合MongoDB连接池(含源码)
💡版本依赖 jdk 17 SpringBoot 3.1.0 Mongo 6.0.8 mybatis-plus 2.0.2 💡环境准备 🌵MongoDB安装 安装教程请查看:一文搞定(linuxwindowsdocker)安装MongoDB 🌵导入依赖 <parent><groupId>org.sp…...

[oeasy]python0082_[趣味拓展]控制序列_清屏_控制输出位置_2J
光标位置 回忆上次内容 上次了解了键盘演化的过程 ESC 从 组合键到 独立按键 ESC的作用 是 进入 控制序列配置 控制信息控制信息 \033[y;xH 设置光标位置\033[2J 清屏 这到底怎么控制???🤔谁来实现这些功能? 控制…...

Zookeeper+kafka
目录 1. Zookeeper定义 2. Zookeeper工作机制 3. Zookeeper特点 4. Zookeeper数据结构 5. Zookeeper应用场景 5.1 统一命名服务 5.2 统一配置管理 5.3 统一集群管理 5.4 服务器动态上下线 5.5 软负载均衡 6. Zookeeper 选举机制 6.1 第一次启动选举机制 6.2 非第一…...

Gpt微信小程序搭建的前后端流程 - 前端小程序部分-1.基础页面框架的静态设计(二)
Gpt微信小程序搭建的前后端流程 - 前端小程序部分-1.基础页面框架的静态设计(二) 在开始这个专栏,我们需要找一个小程序为参考,参考和仿照其界面,聊天交互模式。 这里参考小程序-小柠AI智能聊天,可自行先体验。 该小程序主要提供了…...
Flask进阶:构建RESTful API和数据库交互
在初级教程中,我们已经介绍了如何使用Flask构建基础的Web应用。在本篇中级教程中,我们将学习如何用Flask构建RESTful API,以及如何使用Flask-SQLAlchemy进行数据库操作。 一、构建RESTful API REST(Representational State Tran…...
6.9(Java)二叉搜索树
1.我的代码: public class BinarySearchTree {class TreeNode {public int key;public TreeNode left;public TreeNode right;public TreeNode(int key) {this.key key;}}public TreeNode root; // 根节点// 插入一个元素,注意,不能插入重复的值,如…...
洛谷P2256 一中校运会之百米跑
题目背景 在一大堆秀恩爱的 ** 之中,来不及秀恩爱的苏大学神踏着坚定(?)的步伐走向了 100 100 100 米跑的起点。这时苏大学神发现,百米赛跑的参赛同学实在是太多了,连体育老师也忙不过来。这时体育老师发…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...