SLF4J Spring Boot日志框架
JAVA日志框架
JAVA有好多优秀的日志框架,比如log4j、log4j2、logback、JUL(java.util.logging)、JCL(JAVA Common Logging)等等,logback是后起之秀,是Spring Boot默认日志框架。
今天文章的目标不是研究JAVA的这些日志框架,而是在应用中处于他们前面的日志门面SLF4J,以及初步了解一下Spring Boot的默认日志框架是在什么地方配置的、怎么替换Spring Boot默认的日志框架。
SLF4J
SFL4J,全名Simple Logging Facade for Java,意思是简单JAVA日志门面,是Facade设计模式的一个典型实现。
SFL4J本身并没有日志的任何实现,它只是一个日志门面,目的是为了让应用层能够简单的、方便的使用以上提到的各种不同的日志框架,在代码层不做任何改动的情况下,在最终部署的时候决定具体使用哪一个日志框架。冲这一点,SLF4J就非常NB,能允许程序员在编码的时候不考虑具体使用哪一个日志框架、部署的时候不需要修改一行代码、随意选择日志框架。而且,虽然不是很有必要,但是只要你高兴,应用运行的过程中你都可以随时切换日志框架,比如你刚开始选择log4j2,但是后来觉得不爽想要换成logback,只要你在开发的时候使用了SLF4J,你就可以任性地随时切换。
使用SLF4J
严格来说,SLF4J只需要一个包:slf4j-api-xxx.jar(xxx是版本号) 就可以使用,POM文件中引入:
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency>
之后:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class HelloWorld {public static void main(String[] args) {Logger logger = LoggerFactory.getLogger(HelloWorld.class);logger.info("Hello World");}
}
应用classpath下有任何前述日志框架存在的情况下,以上代码中的日志打印语句就会根据日志框架的配置输出到控制台或者日志文件中了。
SLF4J API及jar包框架
上述案例可以发现,原则上来说,项目Pom文件引入slf4j-api之后,SLF4J就可以正常工作了,但是SLF4J可以正常工作,并不代表整个日志系统可以正常工作,因为SLF4J只是日志门面,需要绑定后端的日志框架之后,日志系统才能正常工作。
我们先看一下SLF4J官网对于SLF4J API的框架图:
可以看出,如果我们采用SLF4J本家的日志框架作为我们应用的日志框架的话,比如用logback的话,我们只需要slf4j-api.jar + logback相关的jar包就可以了,或者我们用slf4j自带的simple日志框架的话,也只需要slf4j-api.jar + slf4j-simple.jar。
但是如果用其他的三方日志框架,比如log4j、或者JUL的话,由于三方框架比如log4j早在SLF4J出现之前就已经占据JAVA日志的半壁江山了,所以早期版本的日志框架不可能适应后面才出现的SLF4J,所以只能SLF4J自己想办法来适应。
SLF4J给出的解决方案就是针对各日志框架的API:
slf4j-log4j12-2.0.10.jar: 为绑定log4j version 1.2,这是一个很古老的版本了,早已宣布寿终正寝了,但是考虑到有些老系统可能还在使用log4j 1.x,所以提供了这个jar包以便兼容。其实从SLF4J 1.7.35之后,slf4j-log4j模块的调用就已经在编译器直接导航到slf4j-reload4j的调用了,所以这个模块对于新版本的SLF4J来说几乎没用了。
slf4j-reload4j-2.0.10.jar:后期版本的SLF4J绑定log4j日志框架,同时需要reload4j.jar(log4j 1.2x之后的替代品)。
slf4j-jdk14-2.0.10.jar: SLF4J绑定JUL(java14之后的内置日志框架)日志框架,同时需要JDK14。
slf4j-nop-2.0.10.jar: 应用不绑定任何日志框架的情况下的SLF4J的默认NOP实现,啥也没干,只是在应用运行进行日志框架绑定的时候不报错。
slf4j-simple-2.0.10.jar: SLF4J自己实现的一个简单的、轻量级日志框架,应该没人用。
slf4j-jcl-2.0.10.jar: 绑定Apache Commons Logging。
logback-classic-xxx.jar: logback日志框架,同时需要logback-core-xxx.jar,可直接支持SLF4J。
将以上jar包放入或移除当前应用(或者通过pom文件)后,就可以轻而易举的实现日志框架的更换,不需要你动一行代码,这就是SLF4J的魔力。
不绑定
如果不引入任何日志框架、代码中又使用了SLF4J的话,会是什么情况?
如果版本是SLF4J 1.6.0 之前的版本,没有加载任何日志框架的情况下,SLF4J在绑定日志框架的时候会抛出异常:NoClassDefFoundError 。因为绑定日志框架的时候找不到org.slf4j.impl.StaticLoggerBinder类。
之后的、SLF4J2.0之前的版本,控制台会打印:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J2.0以上,控制台会打印:
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J 1.6.0之后,如果你的项目并没有加载日志框架,SLF4J提供了一个日志哑实现,叫no-operation (NOP) logger implementation,这个NOP其实就是个假把式,所有的日志打印操作都不会得到任何输出,NOP啥都不干。
桥接API
如果你的已有应用没有使用SLF4J、而是使用JCL或log4j等JAVA日志框架,SLF4J非常贴心的为你提供了两种方案、让你能够以最小代价将as-is系统的日志框架切换到SLF4J上来:
- Bridging legacy APIs:桥接API
- slf4j-migrator:代码迁移工具
桥接API图:
通过桥接API,允许你将既有系统的基于log4j、JCL、JUL等日志框架的系统迁移到SLF4J上来。原理是:jcl-over-slf4j.jar替换原有的commons-logging.jar,应用中对原来的JCL日志框架的调用接口都被替换成了jcl-over-slf4j.jar中的桥接接口,jcl-over-slf4j.jar桥接接口会将日志接口API重新定向到SLF4J中、从而纳入到SLF4J体系中来。
slf4j-migrator代码迁移工具是直接对你的代码动手术的,支持JCL、log4j、JUL的迁移:
Spring Boot默认日志框架
Spring Boot的默认日志框架是在spring-boot-starter中指定的,spring-boot-starter中包含了spring-boot-starter-logging:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId><version>3.1.4</version><scope>compile</scope></dependency>
而spring-boot-starter-logging中引入了logback:
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.11</version><scope>compile</scope></dependency>
所以,Spring Boot的默认日志框架是logback。
如果想要替换默认的日志框架,比如换成log4j2,首先需要在pom文件中加入依赖:
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-reload4j</artifactId><version>2.0.10</version></dependency>
之后直接启动应用,发现:
这个信息是在应用系统的早期就打印出来了,说明日志框架的加载在Spring Boot启动过程中是比较早的。
然后,logback也可以正常工作了(代码中加入log可以检查一下底层日志框架到底是啥):
public HelloWorldController(){log.info("---1=2---");log.info(log.getClass().getName());}
但是我们想要替换logback为log4j2的目标却没有实现!
原因在上面第一张图里已经说了,SLF4J在classpath下发现了两个provider(我们用的是SLF4J2.x版本,通过provider绑定底层日志框架)。
发现两个provider的话,SLF4J会依赖JVM随机绑定一个,我们测试的这个案例是绑定了logback。
怎么能让它绑定log4j呢?
其实通过SLF4J的源码发现了一种方法,就是指定环境变量:
System property for explicitly setting the provider class. If set and the provider could be instantiated, then the service loading mechanism will be bypassed.
Since:2.0.9
如果指定了这个环境变量,SLF4J的加载机制就会被跳过而直接加载指定的provider,比如:
从代码看这个设置也是应该能生效的:
static List<SLF4JServiceProvider> findServiceProviders() {List<SLF4JServiceProvider> providerList = new ArrayList<>();// retain behaviour similar to that of 1.7 series and earlier. More specifically, use the class loader that// loaded the present class to search for servicesfinal ClassLoader classLoaderOfLoggerFactory = LoggerFactory.class.getClassLoader();SLF4JServiceProvider explicitProvider = loadExplicitlySpecified(classLoaderOfLoggerFactory);if(explicitProvider != null) {providerList.add(explicitProvider);return providerList;}
loadExplicitlySpecified方法:
static SLF4JServiceProvider loadExplicitlySpecified(ClassLoader classLoader) {String explicitlySpecified = System.getProperty(PROVIDER_PROPERTY_KEY);if (null == explicitlySpecified || explicitlySpecified.isEmpty()) {return null;}try {String message = String.format("Attempting to load provider \"%s\" specified via \"%s\" system property", explicitlySpecified, PROVIDER_PROPERTY_KEY);Util.report(message);Class<?> clazz = classLoader.loadClass(explicitlySpecified);Constructor<?> constructor = clazz.getConstructor();Object provider = constructor.newInstance();return (SLF4JServiceProvider) provider;} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {String message = String.format("Failed to instantiate the specified SLF4JServiceProvider (%s)", explicitlySpecified);Util.report(message, e);return null;} catch (ClassCastException e) {String message = String.format("Specified SLF4JServiceProvider (%s) does not implement SLF4JServiceProvider interface", explicitlySpecified);Util.report(message, e);return null;}}
如果指定了这个系统参数的话,就直接通过classloader实例化这个provider…但是确实没有测试成功,暂时没找到原因。
我们还有另外一个启用log4j2、停用logback的方案,pom文件排除logback:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></exclusion></exclusions></dependency>
之后刷新pom,发现logback的引用已经消失了。
刷新前:
刷新后:
启动应用:
就会发现Spring Boot项目使用log4j就没有用logback那么舒服了,log4j是需要配置的。随便放一个log4j.properties配置文件就可以正常工作了。
@Slf4j注解
@Slf4j是lombok的一个注解,所以你就能知道他其实没啥,语法糖而已,帮着你在当前类生成一个:
private static final org.slf4j.Logger log =org.slf4j.LoggerFactory.getLogger(Youclass.class);
Ohhh…OK
相关文章:
SLF4J Spring Boot日志框架
JAVA日志框架 JAVA有好多优秀的日志框架,比如log4j、log4j2、logback、JUL(java.util.logging)、JCL(JAVA Common Logging)等等,logback是后起之秀,是Spring Boot默认日志框架。 今天文章的目…...
mysql之导入导出远程备份
文章目录 一、navicat导入导出二、mysqldump命令导入导出2.1导出2.1.1 导出表数据和表结构2.1.2 只导出表结构() 2.2 导入(使用mysqldump导入 包含t _log表的整个数据库 共耗时 20s;)方法一:方法二: 三、LOAD DATA INFILE命令导入导出(只针对单表)设置导…...
Java虚拟机ART 读书笔记 第2章 深入理解Class文件格式
GitHub - Omooo/Android-Notes: ✨✨✨这有一包小鱼干,确定不要吃嘛?( 逃 深入理解Android:Java虚拟机ART 读书笔记 以下内容均来自书中内容 建议看原书哦 第2章 深入理解Class文件格式 2.1 class文件总览 Class文件格式全貌 u4ÿ…...
编程基础 - 初识Linux
编程基础 - 初识Linux 返回序言及专栏目录 文章目录 编程基础 - 初识Linux前言一、Linux发展简介二、现代Linux三、Linux系统各发行版小结 前言 为什么要学习Linux呢?我这Windows用得好好的,简单易用傻瓜式、用的人还超多!但是我要告诉你的…...
c yuv422转yuv420p
思路: yuv422 存储格式为 y u y v y u y v y u y v y u y v yuv420p 存储最简单,先存所以的y,再存u,最后v 所以先把422所有的y存在一起,再提奇数行的u ,偶数行舍弃。提…...
计算机网络 - 路由器查表过程模拟 C++(2024)
1.题目描述 参考计算机网络教材 140 页 4.3 节内容,编程模拟路由器查找路由表的过程,用(目的地址 掩码 下一跳) 的 IP 路由表以及目的地址作为输入,为目的地址查找路由表,找出正确的下一跳并输出结果。 1.…...
实现pytorch版的mobileNetV1
mobileNet具体细节,在前面已做了分析记录:轻量化网络-MobileNet系列-CSDN博客 这里是根据网络结构,搭建模型,用于图像分类任务。 1. 网络结构和基本组件 2. 搭建组件 (1)普通的卷积组件:CBL …...
vue多tab页面全部关闭后自动退出登录
业务场景:主项目是用vue写的单页面应用,但是有多开页面的需求,现在需要在用户关闭了所有的浏览器标签页面后,自动退出登录。 思路:因为是不同的tab页面,我只能用localStorage来通信,新打开一个…...
记一个集群环境部署不完整导致的BUG
一 背景 产品有三个环境:开发测试环境、验收环境、生产环境。 开发测试环境,保持最新的更新; 验收环境,阶段待发布内容; 生产环境,部署稳定内容。 产品为BS架构,后端采用微服务…...
Go zero copy,复制文件
这里使用零拷贝技术复制文件,从内核态操作源文件和目标文件。避免了在用户态开辟缓冲区,然后从内核态复制文件到用户态的问题。 由内核态完成文件复制操作。 调用的是syscall.Sendfile系统调用函数。 //go:build linuxpackage zero_copyimport ("f…...
http协议九种请求方法介绍及常见状态码
http1.0定义了三种: GET: 向服务器获取资源,比如常见的查询请求POST: 向服务器提交数据而发送的请求Head: 和get类似,返回的响应中没有具体的内容,用于获取报头 http1.1定义了六种 PUT:一般是用于更新请求,…...
详解flink exactly-once和两阶段提交
以下是我们常见的三种 flink 处理语义: 最多一次(At-most-Once):用户的数据只会被处理一次,不管成功还是失败,不会重试也不会重发。 至少一次(At-least-Once):系统会保…...
Qt/QML编程学习之心得:QDbus实现service接口调用(28)
D-Bus协议用于进程间通讯的。 QString value = retrieveValue();QDBusPendingCall pcall = interface->asyncCall(QLatin1String("Process"), value);QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);QObject::connect(watcher, SI…...
前端nginx配置指南
前端项目发布后,有些接口需要在服务器配置反向代理,资源配置gzip压缩,配置跨域允许访问等 配置文件模块概览 配置示例 反向代理 反向代理是Nginx的核心功能之一,是指客户端发送请求到代理服务器,代理服务器再将请求…...
接口测试到底怎么做,5分钟时间看完这篇文章彻底搞清楚
01、通用的项目架构 02、什么是接口 接口:服务端程序对外提供的一种统一的访问方式,通常采用HTTP协议,通过不同的url,不同的请求类型(GET、POST),不同的参数,来执行不同的业务逻辑。…...
显示管理磁盘分区 fdisk
显示管理磁盘分区 fdisk fdisk是用于检查一个磁盘上分区信息最通用的命令。 fdisk可以显示分区信息及一些细节信息,比如文件系统类型等。 设备的名称通常是/dev/sda、/dev/sdb 等。 对于以前的设备有可能还存在设备名为 /dev/hd* (IDE)的设备,这个设…...
Hyperledger Fabric 管理链码 peer lifecycle chaincode 指令使用
链上代码(Chaincode)简称链码,包括系统链码和用户链码。系统链码(System Chaincode)指的是 Fabric Peer 中负责系统配置、查询、背书、验证等平台功能的代码逻辑,运行在 Peer 进程内,将在第 14 …...
L1-011 A-B(Java)
题目 本题要求你计算A−B。不过麻烦的是,A和B都是字符串 —— 即从字符串A中把字符串B所包含的字符全删掉,剩下的字符组成的就是字符串A−B。 输入格式: 输入在2行中先后给出字符串A和B。两字符串的长度都不超过10的四次方,并且…...
系列七、Ribbon
一、Ribbon 1.1、概述 Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具,是Netflix发布的一款开源项目,其主要功能是提供客户端的软件负载均衡算法和服务调用,Ribbon客户端组件提供一系列完善的配置项,例如:…...
山东名岳轩印刷包装携专业包装袋盛装亮相2024济南生物发酵展
山东名岳轩印刷包装有限公司盛装亮相2024第12届国际生物发酵展,3月5-7日山东国际会展中心与您相约! 展位号:1号馆F17 山东名岳轩印刷包装有限公司是一家拥有南北两个生产厂区,设计、制版、印刷,营销策划为一体的专业…...
BGP公认必遵属性——Next-hop(一)
BGP公认必遵属性共有三个,分别是:Next-hop、Origin、As-path,本期介绍Next-hop 点赞关注,持续更新!!! Next-hop 华为BGP路由下一跳特点: 默认情况下传给EBGP邻居的BGP路由的下一跳…...
增强Wi-Fi信号的10种方法,值得去尝试
Wi-Fi信号丢失,无线盲区。在一个对一些人来说,上网和呼吸一样必要的世界里,这些问题中的每一个都令人抓狂。 如果你觉得你的Wi-Fi变得迟钝,有很多工具可以用来测试你的互联网速度。你还可以尝试一些技巧来解决网络问题。然而,如果你能获得良好接收的唯一方法是站在无线路…...
第十五章 ECMAScript6新增的常用语法
文章目录 一、声明关键字二、箭头函数三、解构赋值四、展开运算符五、对字符的补充六、Symbol七、对象的简写语法八、Set和Map九、for-of 一、声明关键字 ES6新增的声明关键字: let,const:声明变量class:声明类import,…...
vulhub中的Apache SSI 远程命令执行漏洞
Apache SSI 远程命令执行漏洞 1.cd到ssi-rce cd /opt/vulhub/httpd/ssi-rce/ 2.执行docker-compose up -d docker-compose up -d 3.查看靶场是否开启成功 dooker ps 拉取成功了 4.访问url 这里已经执行成功了,注意这里需要加入/upload.php 5.写入一句话木马 &…...
MSB20M-ASEMI迷你贴片整流桥MSB20M
编辑:ll MSB20M-ASEMI迷你贴片整流桥MSB20M 型号:MSB20M 品牌:ASEMI 封装:UMSB-4 特性:贴片、整流桥 最大平均正向电流:2A 最大重复峰值反向电压:1000V 恢复时间:࿱…...
工程管理系统功能设计与实践:实现高效、透明的工程管理
在现代化的工程项目管理中,一套功能全面、操作便捷的系统至关重要。本文将介绍一个基于Spring Cloud和Spring Boot技术的Java版工程项目管理系统,结合Vue和ElementUI实现前后端分离。该系统涵盖了项目管理、合同管理、预警管理、竣工管理、质量管理等多个…...
【C#】网址不进行UrlEncode编码会存在一些问题
欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是2024年第3篇文章,此篇文章是C#知识点实践序列文章,博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言数据丢失效果请求端代码接口端代码…...
深入Pandas(二):高级数据处理技巧
文章目录 系列文章目录引言时间序列分析可视化示例 高级数据分析技术分组与聚合操作时间序列分析 高级数据操作数据合并与重塑示例:数据合并merge示例:数据合并concat示例:数据重塑 - 透视表 高级索引技巧 结论 系列文章目录 Python数据分析…...
实验8 分析HTTP协议和DNS
实验8 分析HTTP协议和DNS 一、 实验目的及任务 熟悉并掌握wireshark的基本操作,了解网络协议实体间的交互以及报文交换。分析HTTP协议分析DNS协议 二、 实验设备 与因特网连接的计算机网络系统;主机操作系统为Windows;wireshark等软件。 …...
Talk | EMNLP 2023 最佳长论文:以标签为锚-从信息流动的视角分析上下文学习
本期为TechBeat人工智能社区第561期线上Talk。 北京时间1月4日(周四)20:00,北京大学博士生—王乐安的Talk已准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “以标签为锚-从信息流动的视角分析上下文学习”,介绍了他的团队在上下文学…...
维护一个网站要多少钱/安新seo优化排名网站
php修改文件内容的方法:首先通过file_put_contents函数写入文件;然后使fwrite配合fopen进行写入并修改的操作;最后通过file_exists等函数检测文件属性即可。file_put_contents写入文件我们先来学习第一种写入文件的方式:int file_…...
如何利用服务器做网站/windows优化大师是官方的吗
需要用到的命令 #查看挂载df -h#磁盘状态查看fdisk -l#磁盘分区fdisk /dev/adb#格式化磁盘或磁盘分区mkfs.ext4 /dev/adb#挂载磁盘mount /dev/adb /data直接说操作 fdisk -l 查看可挂载磁盘 df -h 查看已经挂在的磁盘 如果对磁盘做分区 fdisk /dev/vdb 输入m,可以查…...
网站空间可以自己做吗/最新国际新闻热点事件
原因一:没有打开MSDTC服务 步骤: Componet Services-->右击My Computer--->Start MSDTCComponet Services-->右击My Computer-->属性--->MSDTC-->安全配置--->勾选上我红线标注的部分。原因二: 防火墙阻止 解决方法&…...
微网站和微信公共平台的区别/广告优化师的工作内容
Linux是什么?linux是一个开源操作系统,是用于与计算机硬件打交道的中间层。操作系统管理系统资源,提供最基本的计算功能,如管理及配置内存,同时还提供一些基本的服务程序,如:文件系统、设备驱动…...
国内wordpress最好的主题/免费开源网站
步骤如下: 一、编译安装两个mysql,步骤如下 下载Mysql ,此处以Mysql-6.0.11-alpha.tar.gz 为例 安装第一个数据库(主数据库) (红色部分为默认数据库文件路径,可改成其他如:data、var等) tar zxvf mysql-6.0.11-alpha.t…...
扮家家室内设计平台/seo关键词优化推广价格
在我东,下下来一个项目总会出现启动不了的问题,这些问题往往在编译的时候发现不了,当你的服务器启动的时候,就是一片片的报错,有些问题可以通过异常的提示信息,判断出来哪里配置错了,但是也有些…...