Spring Boot日志处理

文章目录

  • Spring Boot日志处理
    • 1. 日志存入数据库(AOP)
    • 2. 日志控制台打印与写入文件(logback)

Spring Boot日志处理

1. 日志存入数据库(AOP)

  1. 引入aop依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.6.14</version>
    </dependency>
    
  2. 创建自定义注解类(用于在Controller层使用注解标注哪个方法需要增加日志)

    @interface 注解类,自定义注解

    @Target 用来说明该注解可以被声明在那些元素之前

    ElementType.METHOD说明该注解只能被声明在一个类的方法前

    @Retention 用来说明该注解类的生命周期。

    RetentionPolicy.RUNTIME注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解

    /*** @ClassName Log* @Description 自定义日志注解类* @Author Administrator* @Date 2024/12/23 9:38*/
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Log {// 日志描述String value() default "";
    }
  3. 编写LogAspect增强类与增强方法(我们使用环绕增强around)

    /*** @ClassName LogAspect* @Description 日志增强类与增强方法* @Author Administrator* @Date 2024/12/23 9:41*/
    public class LogAspect {//切入点,指定当使用Log注解时进入环绕增强@Pointcut("@annotation(com.hz.goods.web.log.Log)")public void pointcut() {}@Around("pointcut()")public Object around(ProceedingJoinPoint point) {try {System.out.println("执行环绕增强..............开始");Object result = point.proceed();//执行方法System.out.println("结束..........");return result;} catch (Throwable throwable) {throwable.printStackTrace();}return null;}
    }
    
  4. 创建controller进行测试

    @Log(value = "轮播图列表")
    @GetMapping("/findList")
    public MessageJson<Carousel> findList(){List<Carousel> carousels = carouselService.list();return carousels!=null?MessageJson.success(carousels):MessageJson.error();
    }
    
  5. 开始写入数据库

    创建日志记录表sys_log

    DROP TABLE IF EXISTS `sys_log`;
    CREATE TABLE `sys_log` (
    `ID` bigint(20) NOT NULL AUTO_INCREMENT,
    `USERNAME` varchar(50) DEFAULT NULL COMMENT '用户名',
    `OPERATION` varchar(50) DEFAULT NULL COMMENT '用户操作',
    `TIME` int(11) DEFAULT NULL COMMENT '响应时间',
    `METHOD` varchar(200) DEFAULT NULL COMMENT '请求方法',
    `PARAMS` varchar(500) DEFAULT NULL COMMENT '请求参数',
    `IP` varchar(64) DEFAULT NULL COMMENT 'IP地址',
    `CREATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`ID`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    创建实体类

    @Data
    @TableName("sys_log")
    public class SysLog {
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    private String username;
    private String operation;
    private Integer time;
    private String method;
    private String params;
    private String ip;
    private Date createTime;
    }
    

    编写Mapper层接口

    public interface SysLogMapper extends BaseMapper<SysLog> {
    }
    

    导入工具类HttpContextUtils、IPUtils

    修改LogAspect增强类与增强方法

    @Aspect
    @Component
    public class LogAspect {
    @Autowired
    private SysLogMapper sysLogMapper;
    //切入点,指定当使用Log注解时进入环绕增强
    @Pointcut("@annotation(com.hz.goods.web.log.Log)")
    public void pointcut() {}
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) {try {SysLog sys = new SysLog();sys.setUsername("4072");//设置用户名Long start = System.currentTimeMillis();//开始时间Long end = System.currentTimeMillis();//结束时间Object result = point.proceed();//调用目标方法Long time = end - start;//执行时间sys.setTime(time.intValue());//设置执行时间//获取请求对象HttpServletRequest request = HttpContextUtils.getHttpServletRequest();//获取IP地址sys.setIp(IPUtils.getIpAddr(request));//获取注解描述MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();Log logAnnotation = method.getAnnotation(Log.class);if (logAnnotation != null) {sys.setOperation(logAnnotation.value());//设置操作描述}//获得请求方法名String methodName = point.getTarget().getClass().getName() + "." + point.getSignature().getName();sys.setMethod(methodName);//设置请求方法名// 请求的方法参数值Object[] args = point.getArgs();// 请求的方法参数名称LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paramNames = u.getParameterNames(method);if (args != null && paramNames != null) {String params = "";for (int i = 0; i < args.length; i++) {params += "," + paramNames[i] + ": " + args[i];}sys.setParams(params);}// 保存日志sysLogMapper.insert(sys);return result;} catch (Throwable throwable) {throwable.printStackTrace();}return null;
    }
    }
    
  6. 运行测试@Log

2. 日志控制台打印与写入文件(logback)

  1. 创建logback-spring.xml文件放入resource下,并复制内容到该文件

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration><property name="LOG_CONTEXT_NAME" value="log"/><!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--><property name="LOG_HOME" value="D:/logs" /><!-- 定义日志上下文的名称 --><contextName>${LOG_CONTEXT_NAME}</contextName><!-- 控制台输出 --><!--<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">&lt;!&ndash;格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符&ndash;&gt;<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n</pattern><charset>utf-8</charset></encoder><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter></appender>--><!-- 彩色日志依赖的渲染类 --><conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /><conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /><conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /><!-- 彩色日志格式 --><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%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}}"/><!--1. 输出到控制台--><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!--info日志统一输出到这里--><appender name="file.info" class="ch.qos.logback.core.rolling.RollingFileAppender"><Prudent>true</Prudent><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名,按小时生成--><FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/info/info.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern><!--日志文件保留天数--><MaxHistory>30</MaxHistory><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, --><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符--><pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern><charset>utf-8</charset></encoder><!-- 此日志文件只记录info级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--错误日志统一输出到这里--><appender name="file.error" class="ch.qos.logback.core.rolling.RollingFileAppender"><Prudent>true</Prudent><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名,按天生成--><FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/error/error.%d{yyyy-MM-dd}.%i.log</FileNamePattern><!--日志文件保留天数--><MaxHistory>30</MaxHistory><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, --><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符--><pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern><charset>utf-8</charset></encoder><!-- 此日志文件只记录error级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--warn日志统一输出到这里--><appender name="file.warn" class="ch.qos.logback.core.rolling.RollingFileAppender"><Prudent>true</Prudent><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/warn/warn.%d{yyyy-MM-dd}.%i.log</FileNamePattern><!--日志文件保留天数--><MaxHistory>30</MaxHistory><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, --><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符--><pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern><charset>utf-8</charset></encoder><!-- 此日志文件只记录warn级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>WARN</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--  日志输出级别 --><root level="DEBUG"><appender-ref ref="STDOUT" /><appender-ref ref="file.error" /><appender-ref ref="file.info" /><appender-ref ref="file.warn" /></root></configuration>
    
  2. 配置application.yml文件

    logging:config: classpath:logback-spring.xml
    
  3. 编写controller测试@slf4j

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

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

相关文章

vite6+vue3+ts+prettier+eslint9配置前端项目(后台管理系统、移动端H5项目通用配置)

很多小伙伴苦于无法搭建一个规范的前端项目&#xff0c;导致后续开发不规范&#xff0c;今天给大家带来一个基于Vite6TypeScriptVue3ESlint9Prettier的搭建教程。 目录 一、基础配置1、初始化项目2、代码质量风格的统一2.1、配置prettier2.2、配置eslint2.3、配置typescript 3、…

GitHub的简单操作

引言 今天开始就要开始做项目了&#xff0c;上午是要把git搭好。搭的过程中遇到好多好多的问题。下面就说一下git的简单操作流程。我们是使用的GitHub,下面也就以这个为例了 一、GitHub账号的登录注册 https://github.com/ 通过这个网址可以来到GitHub首页 点击中间绿色的S…

详细的一条SQL语句的执行流程

SQL 语句的执行流程会因数据库管理系统的不同而略有差异&#xff0c;但一般来说&#xff0c;主要包括以下几个阶段&#xff1a; 查询解析 词法分析&#xff1a;数据库系统首先将输入的 SQL 语句按字符流进行扫描&#xff0c;依据词法规则把它分割成一个个的单词&#xff0c;如…

基于CentOS的Docker + Nginx + Gitee + Jenkins部署总结

一、部署环境概述 本文阐述在CentOS系统上运用PowerShell命令部署Docker、Nginx、Gitee&#xff08;文中未详细提及Gitee相关配置&#xff0c;可根据实际情况与其他代码托管平台类比&#xff09;和Jenkins&#xff0c;实现前端自动化部署的流程&#xff0c;包含从系统环境准备…

OpenCV调整图像亮度和对比度

【欢迎关注编码小哥&#xff0c;学习更多实用的编程方法和技巧】 1、基本方法---线性变换 // 亮度和对比度调整 cv::Mat adjustBrightnessContrast(const cv::Mat& src, double alpha, int beta) {cv::Mat dst;src.convertTo(dst, -1, alpha, beta);return dst; }// 使用…

《机器学习》——逻辑回归(下采样)

文章目录 什么是下采样&#xff1f;为什么在逻辑回归中要使用下采样&#xff1f;使用下采样和不使用下采样的区别实例1、实例内容2、实例步骤 什么是下采样&#xff1f; 下采样&#xff08;Down - Sampling&#xff09;是一种数据处理技术&#xff0c;主要用于处理数据集中不同…

Python实现接口签名调用

目录: 1、第三方接口签名调用2、调用结果 1、第三方接口签名调用 import json import requests import hashlib import time import hmac access_key xxxxxxxxxxxxxxx secret_key xxxxxxxxxxxxxxx # 应用信息 def _wps4_sig(method, url, date, body): print(body)if bod…

什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系

我不知道有多少人和我一样&#xff0c;没学习过.netCore&#xff0c;想要学习&#xff0c;但是版本号太多就蒙了&#xff0c;不知道学什么了&#xff0c;这里解释下各个版本的关系 我们一般开始学习微软的时候&#xff0c;都是开始学习的.netframework&#xff0c;常用的就是4…

对比式机器学习揭示了跨物种共享和特异性的脑功能结构|文献速递-视觉大模型医疗图像应用

Title 题目 Contrastive machine learning reveals species -shared and -specific brain functional architecture 对比式机器学习揭示了跨物种共享和特异性的脑功能结构 01 文献速递介绍 猕猴被广泛作为人类的动物模型&#xff0c;用于研究大脑和行为的关键方面&#xf…

中药和西药的区别

中药和西药的区别 一、定义与来源 &#xff08;一&#xff09;中药 中药主要是在中国传统医学理论指导下用于预防、诊断、治疗疾病或调节人体机能的药物。它的来源广泛&#xff0c;包括植物药、动物药、矿物药等。植物药是中药的主要组成部分&#xff0c;例如人参&#xff0…

PostgreSQL学习笔记(一):PostgreSQL介绍和安装

目录 概念 PostgreSQL简介 PostgreSQL的关键特性 1. 标准兼容性 2. 扩展性 3. 数据完整性和可靠性 4. 丰富的数据类型 5. 查询能力 6. 事务和并发控制 7. 扩展和插件 8. 跨平台和多语言支持 9. 高可用性和扩展性 常用场景 安装 Linux apt安装 下载安装包安装 客…

Python跨年烟花

目录 系列文章 写在前面 技术需求 完整代码 下载代码 代码分析 1. 程序初始化与显示设置 2. 烟花类 (Firework) 3. 粒子类 (Particle) 4. 痕迹类 (Trail) 5. 烟花更新与显示 6. 主函数 (fire) 7. 游戏循环 8. 总结 注意事项 写在后面 系列文章 序号直达链接爱…

ABP框架8——仓储的作用及其基础Demo

一、使用仓储的好处 1.提高CRUD接口复用性2.解耦业务逻辑&#xff08;BLL&#xff09;和增删改查&#xff08;CRUD&#xff09;&#xff0c;换ORM特别方便&#xff0c;不需要改应用层&#xff0c;直接改仓储层3.做复杂查询4.事务支持 二、Demo public class BookRepository …

毕设中所学

1、交叉引用 在毕业设计论文Word中交叉引用参考文献_交叉引用如何标注[1~6]-CSDN博客 另&#xff1a;将标号或其他文字改为上标的快捷键是CtrlShift。 图的交叉引用一样&#xff0c;修改引用类型即可。 2、ENVI安装 ENVI5.6 安装教程&#xff0c;新手入门&#xff08;超详细…

git 问题解决记录

在用git上传文件到仓库中出现了2个问题 第一个问题&#xff1a; 需要修改git的代理端口与电脑自己的代理服务器设置中的端口和VPN的端口保持一致&#xff0c; 比如我的端口是7897&#xff0c;就设置 git config --global http.proxy http://127.0.0.1:7897 git config --glo…

DATACOM-DHCP-复习-实验

DHCP 概述工作原理DHCP分配机制 配置配置基于全局地址池的DHCP服务器配置DHCP Relay中继验证 实验配置DHCP中继 参考 概述 动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;用于集中对用户IP地址进行动态管理和…

RK3588+麒麟国产系统+FPGA+AI在电力和轨道交通视觉与采集系统的应用

工业视觉识别系统厂家提供的功能主要包括&#xff1a; 这些厂家通过先进的视觉识别技术&#xff0c;实现图像的采集、处理与分析。系统能够自动化地完成质量检测、物料分拣、设备监控等任务&#xff0c;显著提升生产效率和产品质量。同时&#xff0c;系统具备高度的灵活性和可扩…

物联网控制期末复习

第3章 物联网控制系统的过程通道设计 3.1 模拟量输出通道 3.1.1单模拟量输出通道的构成 计算机控制系统的模拟量输出通道将计算机产生的数字控制信号转换为模拟信号&#xff08;电压或电流&#xff09;作用于执行机构&#xff0c;以实现对被控对象的控制。 多D/A结构&#…

python3中的生成器

一. 简介 前面简单学习了 python3中的迭代器&#xff0c;本文来学习 python3中生成器。 在 Python 中&#xff0c;生成器&#xff08;Generator&#xff09;是一种特殊的迭代器&#xff0c;在 Python 中&#xff0c;生成器&#xff08;Generator&#xff09;是一种特殊的迭代…

数据库运维学习选择

在如今国产化浪潮澎湃的 IT 领域&#xff0c;数据库运维宛如一座充满机遇的宝藏&#xff0c;等待着新人去挖掘。如果你像曾经的我一样&#xff0c;非科班出身、毫无基础&#xff0c;别慌&#xff0c;我以多年奋战在一线的经验&#xff0c;为你照亮前行的路。 一、基础奠基&…