spring boot 之 结合aop整合日志

AOP

该切面仅用于请求日志记录,若有其他需求,在此基础上扩展即可,不多逼逼,直接上代码。

引入切面依赖

<!-- 切面 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

日志切面类

import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;@Slf4j
@Aspect
@Component
public class RequestAop {private static final String START_TIME = "request-start";// 按需修改需要扫描的controller层@Pointcut("execution(* com.example.controller..*.*(..))")public void pointCut() {//该方法仅用于扫描controller包下类中的方法,而不做任何特殊的处理。}@Before("pointCut()")public void doBefore(JoinPoint joinPoint) {HttpServletRequest request =((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();Long start = System.currentTimeMillis();request.setAttribute(START_TIME, start);}@Around("pointCut()")@SneakyThrowspublic Object doAround(ProceedingJoinPoint joinPoint) {Object result = joinPoint.proceed();try {// 获取方法名称String method = joinPoint.getSignature().getName();// 获取类名称String className = joinPoint.getSignature().getDeclaringTypeName();// 获取请求HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();// 请求路径String requestUrl = request.getRequestURL().toString();// 获取请求参数进行打印Signature signature = joinPoint.getSignature();// 参数名数组String[] parameterNames = ((MethodSignature) signature).getParameterNames();// 构造参数组集合List<Object> argList = new ArrayList<>();for (Object arg : joinPoint.getArgs()) {// request/response无法使用toJSONif (arg instanceof HttpServletRequest) {argList.add("request");} else if (arg instanceof HttpServletResponse) {argList.add("response");} else {argList.add(JSON.toJSON(arg));}}log.info("类名:[{}] 方法名:[{}] 请求URL:[{}] 请求参数:{} -> {} 请求结果:{}", className, method, requestUrl, JSON.toJSON(parameterNames), JSON.toJSON(argList), JSON.toJSON(result));} catch (Exception e) {log.error("切面类参数获取失败: {}", e.getMessage());}return result;}@After("pointCut()")public void doAfter(JoinPoint joinPoint) {HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();Long start = (Long) request.getAttribute(START_TIME);Long end = System.currentTimeMillis();// 耗时long costTime = end - start;// 方法名String method = joinPoint.getSignature().getName();log.info("方法名:[{}] 请求耗时:[{}ms]", method, costTime);}
}

日志

级别

日志级别(Log Levels)是指日志消息的优先级或者重要程度,它用于对日志的不同类型和重要程度进行分类和过滤。
不同的日志框架可能使用不同的命名和数量的日志级别,但基本概念是相似的。以下是常见的几个标准日志级别:

1,TRACE(追踪):最低级别的日志,包含详细的调试信息,用于追踪代码的执行流程,如方法的输入参数、内部状态等。
2,DEBUG(调试):用于输出调试信息,在开发和调试阶段使用,帮助排查问题和跟踪代码执行情况以及验证程序的行为。
3,INFO(信息):提供程序运行过程中的重要信息,用于向用户提供一些关键的操作状态和进度,如程序启动关闭、配置项变更等。
4,WARN(警告):表示潜在的问题或异常情况,不会阻止程序继续执行,但可能会影响程序的正常运行,需要开发人员注意。
5,ERROR(错误):表示错误情况,通常表示某个功能或步骤无法正常完成,但程序仍然可以继续运行,需要开发人员关注和解决。
6,FATAL(致命):最高级别的日志,表示最严重的错误,表示程序无法继续运行,会导致应用程序的中断或崩溃,如系统崩溃。

特别说明:以上日志级别由上往下依次增强,而日志级别越高,控制台打印出的日志信息就越少,但打印出的日志信息越重要。

引入lombok依赖

引入lombok后,在需要记录日志的类上添加@Slf4j注解即可。

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.32</version><scope>provided</scope>
</dependency>

日志配置文件

resources下新建目录logslogs下新建logback-spring.xml文件。
仅配置了常用的infoerror级别,其余按需配置即可。

<?xml version="1.0" encoding="utf-8"?>
<configuration><!-- 引入默认得配置文件 --><include resource="org/springframework/boot/logging/logback/defaults.xml"/><!-- 模块名标识日志名称 --><springProperty scope="context" name="springAppName" source="spring.application.name"/><!-- info日志单文件大小限制 --><springProperty scope="context" name="logback.fileInfoLog.maxFileSize" source="logback.fileInfoLog.maxFileSize" defaultValue="1024MB" /><!-- info日志最大保留时长单位天 --><springProperty scope="context" name="logback.fileInfoLog.maxHistory" source="logback.fileInfoLog.maxHistory" defaultValue="30" /><!-- info日志文件总大小,超过该大小,旧得即将删除 --><springProperty scope="context" name="logback.fileInfoLog.totalSizeCap" source="logback.fileInfoLog.totalSizeCap" defaultValue="10GB" /><!-- error日志单文件大小限制 --><springProperty scope="context" name="logback.fileErrorLog.maxFileSize" source="logback.fileErrorLog.maxFileSize" defaultValue="1024MB" /><!-- error日志最大保留时长单位天 --><springProperty scope="context" name="logback.fileErrorLog.maxHistory" source="logback.fileErrorLog.maxHistory" defaultValue="30" /><!-- error日志文件总大小,超过该大小,旧得即将删除 --><springProperty scope="context" name="logback.fileErrorLog.totalSizeCap" source="logback.fileErrorLog.totalSizeCap" defaultValue="10GB" /><!-- 日志目录 --><springProperty scope="context" name="logback.rootDir" source="logback.rootDir" defaultValue="logs"/><!-- 控制台输出得日志格式 --><property name="CONSOLE_LOG_PATTERN"value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/><!-- 日志文件输出得日志格式 --><property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %t [%c:%L]-%m%n"/><!-- 控制台输出 --><appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"><layout class="ch.qos.logback.classic.PatternLayout"><pattern>${CONSOLE_LOG_PATTERN}</pattern></layout></appender><!-- info日志得设定 --><appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>DENY</onMatch><onMismatch>ACCEPT</onMismatch></filter><encoder><pattern>${FILE_LOG_PATTERN}</pattern></encoder><file>${logback.rootDir}/${springAppName}.log</file><!--滚动策略--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" ><!--路径--><fileNamePattern>${logback.rootDir}/%d{yyyy-MM,aux}/%d{yyyy-MM-dd,aux}/${springAppName}-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern><maxFileSize>${logback.fileInfoLog.maxFileSize}</maxFileSize><maxHistory>${logback.fileInfoLog.maxHistory}</maxHistory><totalSizeCap>${logback.fileInfoLog.totalSizeCap}</totalSizeCap><cleanHistoryOnStart>true</cleanHistoryOnStart></rollingPolicy></appender><!-- 错误日志 --><appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>ERROR</level></filter><encoder><pattern>${FILE_LOG_PATTERN}</pattern></encoder><file>${logback.rootDir}/${springAppName}-error.log</file><!--滚动策略--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" ><!--路径--><fileNamePattern>${logback.rootDir}/%d{yyyy-MM,aux}/%d{yyyy-MM-dd,aux}/${springAppName}-error-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern><maxFileSize>${logback.fileErrorLog.maxFileSize}</maxFileSize><maxHistory>${logback.fileErrorLog.maxHistory}</maxHistory><totalSizeCap>${logback.fileErrorLog.totalSizeCap}</totalSizeCap><cleanHistoryOnStart>true</cleanHistoryOnStart></rollingPolicy></appender><appender name="ASYNC_consoleLog" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="consoleLog"/></appender><appender name="ASYNC_fileInfoLog" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="fileInfoLog"/></appender><appender name="ASYNC_fileErrorLog" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="fileErrorLog"/></appender><root level="info"><appender-ref ref="ASYNC_consoleLog" /><appender-ref ref="ASYNC_fileInfoLog" /><appender-ref ref="ASYNC_fileErrorLog" /></root></configuration>

application.yml配置

# spring.application.name 必须配置
# 因为上述日志配置文件指定了项目启动后输出的日志文件命名,即为该配置
spring:application:name: LogApplicationlogging:
# 指定自定义的配置文件config: classpath:logs/logback-spring.xml
# 指定输出的日志级别
# trace < debug < info < warn < error
# 例如:指定输出级别为info,则trace和debug均不会输出level:root: info #该方式指定的是整个项目的日志输出级别# com.example.controller: debug #也可以指定具体某个包下的日志输出级别

结果展示

在这里插入图片描述
以上述配置为例,项目启动后会在项目下生成logs目录,该目录下会有两个日志文件:LogApplication.logLogApplication-error.log,项目中所有log.error()日志都会输出到LogApplication-error.log,其余日志则输出到LogApplication.log.

拓展

将指定的类产生的日志输出到指定的文件中。
示例:RequestAop切面中产生的是所有的请求记录,将该类的日志放入指定的文件。

logback-spring.xml新增配置,未添加请求日志文件的大小限制、存放时间等配置,若有需求,按infoerror配置仿写即可。

    <!-- 接口请求日志 --><appender name="requestLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>DENY</onMatch><onMismatch>ACCEPT</onMismatch></filter><encoder><pattern>${FILE_LOG_PATTERN}</pattern></encoder><!--此处配置输出文件名称为 应用名-request.log --><file>${logback.rootDir}/${springAppName}-request.log</file><!--滚动策略--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" ><!--路径--><fileNamePattern>${logback.rootDir}/%d{yyyy-MM,aux}/%d{yyyy-MM-dd,aux}/${springAppName}-request-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern><maxFileSize>${logback.fileInfoLog.maxFileSize}</maxFileSize><maxHistory>${logback.fileInfoLog.maxHistory}</maxHistory><totalSizeCap>${logback.fileInfoLog.totalSizeCap}</totalSizeCap><cleanHistoryOnStart>true</cleanHistoryOnStart></rollingPolicy></appender><appender name="ASYNC_requestLog" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="requestLog"/></appender><!--将切面类所在包的位置配置上--><logger name="com.example.aop.RequestAop" additivity="false" level="INFO"><appender-ref ref="ASYNC_requestLog"/></logger>

在这里插入图片描述
以上述配置为例,项目启动后会在项目下生成logs目录,该目录下会有三个日志文件:LogApplication.logLogApplication-error.logLogApplication-request.log,项目中所有log.error()日志都会输出到LogApplication-error.logRequestAop切面类的日志会输出到LogApplication-request.log,其余日志则输出到LogApplication.log.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/17264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】set与map

目录 一、键值对 二、set 1. set的模板参数列表 2. set的构造 3. set的迭代器 4. set的容量 5. set的修改 6. set的查找 三、map 1. map的模板参数列表 2. map的构造 3. map的迭代器 4. map的容量 5. map的修改 6. map的查找 一、键值对 用来表示具有一一对应关…

SARscape5.7已经支持3米陆探一号(LT-1)数据处理

SARsacpe5.6.2.1版本已经开始支持LT-1的数据处理&#xff0c;由于当时只获取了12米的条带模式2&#xff08;STRIP2&#xff09;例子数据&#xff0c;对3米条带模式1&#xff08;STRIP1&#xff09;数据的InSAR处理轨道误差挺大&#xff0c;可能会造成干涉图异常。 SARsacpe5.7最…

三十篇:动脉脉搏:企业业务处理系统的生命力

动脉脉搏&#xff1a;企业业务处理系统的生命力 1. 引言 在数字经济的浪潮下&#xff0c;企业之间的竞争已不仅仅是产品和服务的竞争&#xff0c;更是信息处理能力的竞争。业务处理系统&#xff08;Transaction Processing System, TPS&#xff09;是企业信息系统架构的基础&a…

Python3 笔记:Python之禅

打开Python Shell&#xff0c;输入import this&#xff0c;按回车键运行程序。 Beautiful is better than ugly. 优雅胜于丑陋。 Explicit is better than implicit. 明确胜于含糊。 Simple is better than complex. 简单胜于复杂。

图形学初识--纹理采样和Wrap方式

文章目录 前言正文1、为什么需要纹理采样&#xff1f;2、什么是纹理采样&#xff1f;3、如何进行纹理采样&#xff1f;&#xff08;1&#xff09;假设绘制区域为矩形&#xff08;2&#xff09;假设绘制区域为三角形 4、什么是纹理的Wrap方式&#xff1f;5、有哪些纹理的Wrap方式…

洪师傅代驾系统开发 支持公众号H5小程序APP 后端Java源码

代驾流程图 业务流程图 管理端设置 1、首页装修 2、师傅奖励配置 师傅注册后,可享受后台设置的新师傅可得的额外奖励; 例:A注册了师傅,新人奖励可享受3天,第一天的第一笔订单完成后可得正常佣金佣金*奖励比例 完成第二笔/第三笔后依次可得正常佣金佣金*奖励比例 完成的第四…

牛客NC166 连续子数组的最大和(二)【中等 前缀和数组+动态规划 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/11662ff51a714bbd8de809a89c481e21 思路 前缀和数组动态规划Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规…

小短片创作-优化场景并输出短片(二)

1、什么是潮湿感 什么是潮湿感&#xff1a;基础颜色变化粗糙度变化表面渗入性 1.基础颜色变化&#xff1a;潮湿的地方颜色会变深 2.粗糙度变化&#xff1a;镜面粗糙度为0&#xff0c;潮湿的地方粗糙度会变低 3.表面渗入性&#xff1a;主要看材质是否防水 2、调整场景材质增…

YOLOv8+PyQt5鸟类检测系统完整资源集合(yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

资源包含可视化的鸟类检测系统&#xff0c;基于最新的YOLOv8训练的鸟类检测模型&#xff0c;和基于PyQt5制作的可视化鸟类检测系统&#xff0c;包含登陆页面、注册页面和检测页面&#xff0c;该系统可自动检测和识别图片或视频当中出现的各种鸟类&#xff0c;以及自动开启摄像头…

Linux汉化Jupyter Notebook

要在Linux系统中使Jupyter Notebook汉化&#xff0c;可以通过安装jupyterlab-language-pack-zh-CN扩展来实现。以下是具体步骤和示例代码&#xff1a; 打开终端。 执行以下命令以安装Jupyter Notebook的中文语言包&#xff1a; pip install jupyterlab-language-pack-zh-CN …

【CSharp】将ushort数组保存为1通道位深16bit的Tiff图片

【CSharp】将ushort数组保存为1通道位深16bit的Tiff图片 1.背景2.接口 1.背景 System.Drawing.Common 是一个用于图像处理和图形操作的库&#xff0c;它是 System.Drawing 命名空间的一部分。由于 .NET Core 和 .NET 5 的跨平台特性&#xff0c;许多以前内置于 .NET Framework…

微信小程序上传包过大的最全解决方案!

微信小程序的发布大小限制是2MB。然而一个程序怎么能这么小&#xff1f; 介绍一下项目中的经验。 新项目 如果是刚开始做的新项目&#xff0c;一定确定好自己要用的Ui框架&#xff0c;而且确定之后&#xff0c;千万不要引入别的&#xff0c;否则占大小&#xff01;&#xff0…

HNCTF

HNCTF 文章目录 HNCTFBabyPQEZmathez_Classicf(?*?)MatrixRSABabyAESIs this Iso? BabyPQ nc签到题&#xff0c;跟端口连接拿到n和phin n 8336450100232098099043686671148282601664696810002345240872579498695511770993195704402414029892029461830476866385453475141207…

【开源】加油站管理系统 JAVA+Vue.js+SpringBoot+MySQL

目录 一、项目介绍 论坛模块 加油站模块 汽油模块 二、项目截图 三、核心代码 一、项目介绍 Vue.jsSpringBoot前后端分离新手入门项目《加油站管理系统》&#xff0c;包括论坛模块、加油站模块、汽油模块、加油模块和部门角色菜单模块&#xff0c;项目编号T003。 【开源…

矩阵对角化在机器学习中的奥秘与应用

在机器学习的广阔领域中&#xff0c;矩阵对角化作为一种重要的数学工具&#xff0c;扮演着不可或缺的角色。从基础的线性代数理论到复杂的机器学习算法&#xff0c;矩阵对角化都在其中发挥着重要的作用。 矩阵对角化的概念与原理 矩阵对角化是矩阵理论中的一个基本概念&#x…

综合布线管理软件有何作用?

当客户问及“综合布线管理软件究竟有何作用&#xff1f;” 我们通常这样回答&#xff1a; 综合布线管理软件&#xff0c;作为运维管理的得力助手&#xff0c;其核心功能旨在确保布线系统的稳定运行与快速响应。 首先&#xff0c;这款软件通过构建标准化的运维管理流程&#…

四川汇聚荣科技有限公司好不好?

在当今科技飞速发展的时代&#xff0c;企业要想在激烈的市场竞争中脱颖而出&#xff0c;不仅需要先进的技术支持&#xff0c;还需要优质的服务和良好的口碑。那么&#xff0c;四川汇聚荣科技有限公司是否具备这些条件呢?接下来&#xff0c;我们将从公司实力、服务质量、客户反…

如何根据系统的业务场景需求定制自己的线程池?

如何根据系统的业务场景需求定制自己的线程池? 1、背景2、生产中应当如何使用线程池才比较合理呢?2.1、指定线程数量2.2、选择合适的工作队列2.3、自定义线程工厂2.4、选择合适的拒绝策略3、自定义线程池代码案例1、背景 线程池有那么多的参数和类型,在实际的开发中,我们应…

Java后端面经

1.可重复读&#xff0c;已提交读&#xff0c;这两个隔离级别表现的现象是什么&#xff0c;区别是什么样的&#xff1f; 可重复读&#xff1a;表示整个事务看到的事务和开启后的事务能看到的数据是一致的&#xff0c;既然数据是一致的&#xff0c;所以不存在不可重复读。而且不…

力扣算法之1045. 买下所有产品的客户

力扣传送门 题解注释 Customer表中对应的customer_id对应的product_key去重后要全部存在于Product表中的product_key 我的解 SELECT customer_id FROM Customer GROUP BY customer_id HAVING COUNT(DISTINCT product_key)(SELECT COUNT(DISTINCT product_key) FROM Product…