slf4j日志框架和logback详解
slf4j作用及其实现原理
SLF4J(Simple Logging Facade for Java)是一种日志框架的抽象层,它并不是一个具体的日志实现,而是一个接口或门面(Facade),旨在为各种不同的日志框架提供一个统一的API。以下是SLF4J的作用及其实现原理的详细说明:
SLF4J的作用
统一的日志API:
SLF4J提供了一套通用的API,允许开发人员在代码中使用相同的日志记录方法,无论底层的日志实现是什么。
这样做可以提高代码的可移植性和可维护性,因为更换日志框架只需要改变依赖关系,而不需要修改代码中的日志调用。
避免绑定特定日志框架:
开发人员不必在代码中直接引用特定的日志框架(如Log4j, Logback等),而是通过SLF4J的接口进行日志操作。
这种解耦使得在项目中切换日志框架变得更加容易,减少了依赖锁定的问题。
性能优化:
SLF4J设计时考虑到了性能因素,例如,它提供了条件日志记录功能,只有当日志级别被启用时,才会执行字符串拼接等昂贵的操作。
实现原理
桥接机制:
SLF4J使用桥接器(Bridge)机制将日志调用转发给具体的日志框架实现。
当你引入SLF4J后,还需要添加一个桥接器库,例如slf4j-log4j12或slf4j-logback,这取决于你想要使用的具体日志框架。
静态绑定:
SLF4J通过静态绑定(Static Binding)来决定使用哪个具体的日志框架实现。这意味着在编译时,SLF4J会检查类路径上的可用实现,并选择其中一个。
如果没有找到任何实现,SLF4J会退回到一个简单的实现slf4j-simple,这通常只用于开发和测试环境。
动态绑定:
尽管SLF4J主要使用静态绑定,但在某些情况下,它也支持动态绑定,即在运行时更改日志框架的实现。不过,这通常不推荐,因为它可能会导致不可预测的行为。
日志级别:
SLF4J支持多种日志级别,包括TRACE, DEBUG, INFO, WARN, ERROR,并且可以通过配置文件或编程方式设置每个类或包的日志级别。
通过上述机制,SLF4J能够作为一个轻量级的门面,为Java应用程序提供灵活、高效和统一的日志记录功能。
参考:
https://www.cnblogs.com/xrq730/p/8619156.html
logback详解
Logback 是一个高性能的日志框架,专为 Java 平台设计,由 Ceki Gülcü 创建,他是 Log4j 的作者之一。Logback 作为 Log4j 的继承者,不仅在性能上有所提升,还提供了更强大的配置能力和更好的模块化设计。下面是 Logback 的详细解析:
Logback 的组成部分
Logback 被分为三个模块:
logback-core:这是 Logback 的核心模块,包含了所有基本的日志处理逻辑,如日志事件、日志上下文和日志状态。
logback-classic:构建在 logback-core 上,实现了 SLF4J 的 API,因此可以作为 SLF4J 的后端。同时,它也兼容 Log4j 的 API,为从 Log4j 迁移的应用提供了便利。
logback-access:这是一个可选模块,用于集成 Servlet 容器,可以捕获 HTTP 请求和响应信息,并将其记录到日志中。
Logback 的组件:
Logback 的配置文件(通常是 XML 格式)由以下几种主要组件构成:
Appender:日志消息的目标,可以是控制台、文件、数据库、网络等。常见的 Appender 包括 ConsoleAppender、FileAppender、RollingFileAppender 等。
Layout:定义日志消息的格式。Logback 提供了多种 Layout,如 PatternLayout、XMLLayout 等。
Encoder:在 Logback 1.1 版本之后,Layout 被 Encoder 替代,用于控制日志消息的格式化。PatternLayoutEncoder 是最常用的 Encoder。
Logger:代表一个日志类别,通常与类名或包名对应。每个 Logger 都有一个日志级别,如 TRACE、DEBUG、INFO、WARN、ERROR 等。
Root Logger:是所有 Logger 的父类,如果没有为特定的 Logger 设置日志级别,则会继承 Root Logger 的日志级别。
Filter:用于控制哪些日志事件应该被处理。Filter 可以基于日志级别、日志消息内容等条件过滤日志。
配置示例
见下文配置
性能优化
Logback 在设计时特别关注性能,通过优化日志事件的处理流程和减少对象创建等方式,提高了日志记录的速度。此外,Logback 还支持异步日志记录,进一步提升了高并发场景下的性能表现。
参考:Java日志框架:logback详解 - 五月的仓颉 - 博客园 (cnblogs.com)
SpringBoot配置SLF4J日志全过程
在 Spring Boot 中配置 SLF4J (Simple Logging Facade for Java) 日志的过程通常包括以下几个步骤:
1. 添加依赖
确保你的项目中有 SLF4J 和 Logback 的依赖。Spring Boot 默认会包含这些依赖,但如果你使用的是自定义的配置或者老版本的 Spring Boot,你可能需要在 Maven 或 Gradle 的构建文件中手动添加它们。
Maven 示例:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId>
</dependency>
2. 配置日志级别和输出
Spring Boot 使用 Logback 作为 SLF4J 的默认实现,并且会在类路径下查找 logback.xml 或者 application.properties 文件来配置日志。
使用 logback.xml
创建一个名为 logback.xml 的文件在 src/main/resources 目录下,然后在其中配置日志输出和日志级别。
示例配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!-- 日志存放路径 --><property name="log.path" value="/Logger/logs" /><!-- 日志输出格式 --><property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统日志输出 --><appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-info.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>INFO</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><appender name="file_debug" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-debug.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-debug.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>DEBUG</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-error.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>ERROR</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><!-- 用户访问日志输出 --><appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-user.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天回滚 daily --><fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统模块日志级别控制 --><logger name="com.hm" level="info" /><!-- Spring日志级别控制 --><logger name="org.springframework" level="warn" /><root level="info"><appender-ref ref="console" /></root><!--系统操作日志--><root level="info"><appender-ref ref="file_info" /><appender-ref ref="file_error" /><appender-ref ref="file_debug" /></root><!--系统用户操作日志--><logger name="sys-user" level="info"><appender-ref ref="sys-user"/></logger>
</configuration>
3. 使用 SLF4J API 记录日志
在你的 Java 类中,使用 SLF4J 的 Logger API 来记录日志。
示例代码:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class ExampleService {private static final Logger logger = LoggerFactory.getLogger(ExampleService.class);public void doSomething() {logger.info("Doing something...");}
}
4. 测试日志输出
运行你的应用程序并检查控制台输出和日志文件,确认日志是否按照预期被记录。
以上就是 Spring Boot 中配置 SLF4J 日志的全过程。你可以根据实际需求调整日志级别、输出格式和目标位置。
检查项目所在盘的/Logger/logs目录是否有日志文件即可。
参考:
SpringBoot配置SLF4J日志全过程_java_脚本之家
相关文章:
slf4j日志框架和logback详解
slf4j作用及其实现原理 SLF4J(Simple Logging Facade for Java)是一种日志框架的抽象层,它并不是一个具体的日志实现,而是一个接口或门面(Facade),旨在为各种不同的日志框架提供一个统一的API。…...
解决@Data与@Builder冲突的N种策略
前言 在Java项目中,Lombok的Data和Builder注解因其便捷性深受开发者喜爱,但两者并用时可能引发构造方法冲突。本文将全面解析这一问题的根源,并介绍包括利用实验性思路探讨的Tolerate概念在内的多种解决方案,确保您在实践中游刃有…...
一文看懂LUT(Lookup Table)查找表
文章目录 原理方法具体步骤和代码实现 查找表(Lookup Table,LUT)方法是一种通过预先计算并存储函数值来加速计算的方法。对于激活函数(例如ReLU),使用LUT可以在一定范围内通过查找预计算的值来近似函数计算…...
06 人以群分 基于邻域的协同过滤算法
这一讲我们将正式进入算法内容的学习。 推荐算法本质 推荐算法本质上是一一种信息处理方法,它将用户信息和物品信息处理后,最终输出了推荐结果。因为 05 讲中基于热门推荐、基于内容推荐、基于关联规则推荐等方法比较粗放,所以推荐结果往往…...
SQL性能下降的原因
一、SQL性能下降的原因 主要是性能下降SQL慢、执行时间长、等待时间长 不是一条SQL抓出来就要优化,在真实的生产环境下这种故障第一个要去复线,有可能去排查的时候没,所以没法复线。 可能需要它跑半天或者一天来缩小筛查的范围,…...
js的原型
原型: 1定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。 通过该构造函数产生的对象,以继承该原型的属性和方法。原型也是对象。 2.利用原型特点和概念,可以提取共有属性。 3.对象如…...
FastAPI 学习之路(三十七)元数据和文档 URL
实现前的效果 那么如何实现呢,第一种方式如下: from routers.items import item_router from routers.users import user_router""" 自定义FastApi应用中的元数据配置Title:在 OpenAPI 和自动 API 文档用户界面中作为 API 的…...
C 语言结构体
本博客涉及的结构体知识有: 1.0:结构体的创建和使用 2.0: typedef 关键字与#define 关键字的区别 3.0: 结构体成员的访问【地址访问与成员访问】 4.0: 结构体嵌套调用 5.0 数组访问赋值结构体成员 ...... 1.0:结构体的创建和使用 结…...
MySQl高级篇-主从复制
主从复制 复制的基本原理 slave会从master读取binlog来进行数据同步 MySQL复制过程分成三步: master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;slave将master的binary log events拷贝到它的中继日志(r…...
JMeter案例分享:通过数据验证的错误,说说CSV数据文件设置中的线程共享模式
前言 用过JMeter参数化的小伙伴,想必对CSV Data Set Config非常熟悉。大家平时更关注变量名称,是否忽略首行等参数,其余的一般都使用默认值。然而我最近遇到一个未按照我的预想读取数据的案例,原因就出在最后一个参数“线程共享模…...
数学建模·Topsis优劣解距离法
Topsis优劣解 一种新的评价方法,特点就是利用原有数据,客观性强。 相较于模糊评价和层次评价 更加客观,充分利用原有数据,精确反映方案差距 基本原理 离最优解最近,离最劣解越远 具体步骤 正向化 代码与原理与熵权…...
数学建模中常用的数据处理方法
常用的数据处理方法 本文参考 B站西电数模协会的讲解视频 ,只作笔记提纲,想要详细学习具体内容请观看 up 的学习视频。国赛的 C 题一般数据量比较大。 这里介绍以下两种方法: 数据预处理方法 数据分析方法 数据预处理方法 1. 数据清洗 为…...
C嘎嘎:函数模版和类模版
目录 泛型编程 函数模版 函数模版概念 函数模版的格式 函数模版的原理 函数模版的实例化 函数参数的匹配原则 类模版 类模版的定义格式 类模版的实例化 泛型编程 如何实现一个通用的交换函数呢 void Swap(int& left, int& right) {int temp left;left rig…...
使用 Apache Pulsar 构建弹性可扩展的事件驱动应用
本视频来自 2024 Apache Pulsar 欧洲峰会,由 David Kjerrumgaard, 《Pulsar in Action》书作者给大家带来的《使用 Apache Pulsar 构建弹性可扩展的事件驱动应用》分享。 嘉宾|David Kjerrumgaard,Apache Pulsar Committer,《Pul…...
【国产开源可视化引擎Meta2d.js】视频
视频 meta2d 支持Html音视频。 // 音频 const pen {name: video,x: 100,y: 100,width: 100,height: 10,audio: https://down.ear0.com:3321/preview?soundid37418&typemp3,autoPlay: true, }; meta2d.addPen(pen); meta2d.inactive();// 视频 const pen {name: video,x…...
零信任网络安全
随着数字化转型的发生,网络边界也在不断被重新定义,因此,组织必须使用新的安全方法重新定义其防御策略。 零信任是一种基于“永不信任,永远验证”原则的安全方法,它强调无论在公司内部或外部,任何用户、设…...
Python酷库之旅-第三方库Pandas(022)
目录 一、用法精讲 55、pandas.lreshape函数 55-1、语法 55-2、参数 55-3、功能 55-4、返回值 55-5、说明 55-6、用法 55-6-1、数据准备 55-6-2、代码示例 55-6-3、结果输出 56、pandas.wide_to_long函数 56-1、语法 56-2、参数 56-3、功能 56-4、返回值 56-5…...
数据建设实践之大数据平台(一)准备环境
大数据组件版本信息 zookeeper-3.5.7hadoop-3.3.5mysql-5.7.28apache-hive-3.1.3spark-3.3.1dataxapache-dolphinscheduler-3.1.9大数据技术架构 大数据组件部署规划 node101node102node103node104node105datax datax datax ZK ZK ZK RM RM NM...
VUE2用elementUI实现父组件中校验子组件中的表单
需求是VUE2框架用elementUI写复杂表单组件,比如,3个相同功能的表单共用一个提交按钮,把相同功能的表单写成一个子组件,另一个父组件包含子组件的重复调用和一个提交按钮,并且要求提交时校验必填项。 注意: …...
人工智能算法工程师(中级)课程9-PyTorch神经网络之全连接神经网络实战与代码详解
大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(中级)课程9-PyTorch神经网络之全连接神经网络实战与代码详解。本文将给大家展示全连接神经网络与代码详解,包括全连接模型的设计、数学原理介绍,并从手写数字识别到猫狗识…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
