当前位置:网站首页>JCL 和 SLF4J
JCL 和 SLF4J
2022-07-01 08:37:00 【xx985】
常见的日志实现:JUL、log4j、logback、log4j2
常见的日志门面 :JCL、slf4j
出现顺序 :log4j -->JUL-->JCL--> slf4j --> logback --> log4j2
JCL
JCL简介
全称为Jakarta Commons Logging,是Apache提供的一个通用日志API。
用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的jul, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。
当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱。所以使用common-logging,通常都是配合着log4j以及其他日志框架来使用。
使用它的好处就是,代码依赖是common-logging而非log4j的API, 避免了和具体的日志API直接耦合,在有必要时,可以更改日志实现的第三方库。
JCL 有两个基本的抽象类:
Log:日志记录器
LogFactory:日志工厂(负责创建Log实例)
先导入依赖
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>public class JCLTest01 {
@Test
public void test01(){
/*
我们暂时没有导入第三方的日志框架,例如log4j
默认的情况下,会使用JUL日志框架做日志的记录操作
JCL使用原则:
如果有log4j,优先使用log4j
如果没有任何第三方日志框架的时候,我们使用的就是JUL
*/
Log log = LogFactory.getLog(JCLTest01.class);
log.info("info信息");
}
}总结:
默认情况使用的是JUL,但是在集成了log4j环境后,使用的又是log4j
通过测试观察,虽然日志框架发生了变化,但是代码完全没有改变日志门面技术的好处:
门面技术是面向接口的开发,不再依赖具体的实现类,减少代码的耦合性
可以根据实际需求,灵活的切换日志框架
统一的API,方便开发者学习和使用
统一的配置管理便于项目日志的维护工作
SLF4J
简单日志门面(Simple Logging Facade For Java) SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。 当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。所以我们可以得出SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。
官方网站: https://www.slf4j.org/
导入依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--slf4j 自带的简单日志实现 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>SLF4J对日志的级别划分
trace、debug、info、warn、error五个级别
trace:日志追踪信息
debug:日志详细信息
info:日志的关键信息 默认打印级别
warn:日志警告信息
error:日志错误信息
在没有任何其他日志实现框架集成的基础之上
slf4j使用的就是自带的框架slf4j-simple
slf4j-simple也必须以单独依赖的形式导入进来<!--<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency>-->
@Test
public void test03(){
Logger logger = LoggerFactory.getLogger(SLF4JTest01.class);
String name = "zs";
int age = 23;
//logger.info("学生信息-姓名:"+name+";年龄:"+age);
//logger.info("学生信息-姓名:{},年龄:{}",new Object[]{name,age});
logger.info("学生信息-姓名:{},年龄:{}",name,age);
try {
int n = 1/0;
} catch (ClassNotFoundException e) {
//打印栈追踪信息
//e.printStackTrace();
//e是引用类型对象,不能根前面的{}做有效的字符串拼接
//logger.info("具体错误是:{}",e);//错误写法
//我们不用加{},直接后面加上异常对象e即可
logger.info("具体错误是:",e);
}
}SLF4J日志门面,共有3种情况对日志实现进行绑定
1.在没有绑定任何日志实现的基础之上,日志是不能够绑定实现任何功能的
值得大家注意的是,通过我们刚刚的演示,slf4j-simple是slf4j官方提供的
使用的时候,也是需要导入依赖,自动绑定到slf4j门面上
如果不导入,slf4j 核心依赖是不提供任何实现的
2.logback和simple(包括nop)
都是slf4j门面时间线后面提供的日志实现,所以API完全遵循slf4j进行的设计
那么我们只需要导入想要使用的日志实现依赖,即可与slf4j无缝衔接
值得一提的是nop虽然也划分到实现中了,但是他是指不实现日志记录(后续课程)
3.log4j和JUL(这两个需要导入适配器)
都是slf4j门面时间线前面的日志实现,所以API不遵循slf4j进行设计
通过适配桥接的技术,完成的与日志门面的衔接<!-- 导入log4j适配器依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency><!-- 导入jul适配器依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.25</version>
</dependency>
在真实生产环境中,slf4j只绑定一个日志实现框架就可以了
绑定多个,默认使用导入依赖的第一个,而且可能会产生没有必要的警告信息
需求:
假设我们项目一直以来使用的是log4j日志框架
但是随着技术和需求的更新换代
log4j已然不能够满足我们系统的需求
我们现在就需要将系统中的日志实现重构为 slf4j+logback的组合
在不触碰java源代码的情况下,将这个问题给解决掉
此时需要将日志替换为slf4j+logback
我们既然不用log4j了,就将log4j去除
将slf4j日志门面和logback的日志实现依赖加入进来
这样做,没有了log4j环境的支持,编译报错这个时候就需要使用桥接器来做这个需求了
桥接器解决的是项目中日志的重构问题,当前系统中存在之前的日志API,
可以通过桥接转换到slf4j的实现桥接器的使用步骤:
1.去除之前旧的日志框架依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.添加slf4j提供的桥接组件
log4j相关的桥接器
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
桥接器加入后,代码编译就不报错了
注意: 在桥接器加入之后,适配器就没有必要加入了 桥接器和适配器不能同时导入依赖 桥接器如果配置在适配器的上方,则运行报错,不同同时出现 桥接器如果配置在适配器的下方,则不会执行桥接器,没有任何的意义
边栏推荐
- Qt的模型与视图
- 《单片机原理及应用》—定时器、串行通信和中断系统
- I would like to know the process of stock registration and account opening by mobile phone? In addition, is it safe to open a mobile account?
- Audio audiorecord create (I)
- 《微机原理》—总线及其形成
- 分享2022上半年我读过的7本书
- Matlab [functions and images]
- Redis源码学习(29),压缩列表学习,ziplist.c(二)
- Guidelines and principles of did
- 嵌入式工程师面试题3-硬件
猜你喜欢
![Matlab [function derivation]](/img/ba/9fb9da8a458d0c74b29b21a17328fc.png)
Matlab [function derivation]

Introduction to 18mnmo4-5 steel plate executive standard and delivery status of 18mnmo4-5 steel plate, European standard steel plate 18mnmo4-5 fixed rolling
![[untitled]](/img/40/560c597d53d27eff860644cd7c3030.png)
[untitled]

Public network cluster intercom +gps visual tracking | help the logistics industry with intelligent management and scheduling

如何做好固定资产管理?易点易动提供智能化方案

Audio audiorecord create (I)

【js逆向】md5加密参数破解

MAVROS发送自定义话题消息给PX4

What is 1cr0.5mo (H) material? 1cr0.5mo (H) tensile yield strength

Centos7 shell script one click installation of JDK, Mongo, Kafka, FTP, PostgreSQL, PostGIS, pgrouting
随机推荐
MD文档中插入数学公式,Typora中插入数学公式
Tita OKR: a dashboard to master the big picture
基础:3.opencv快速入门图像和视频
What are the differences between the architecture a, R and m of arm V7, and in which fields are they applied?
个人装修笔记
Nacos - 配置管理
Intelligent water supply system solution
长安链同步节点配置与启动
factory type_id::create过程解析
C语言指针的进阶(上篇)
DID的使用指南,原理
【面试必刷101】链表
Introduction to R language
TypeError: __ init__ () got an unexpected keyword argument ‘autocompletion‘
Shell脚本-位置参数(命令行参数)
如何一站式高效管理固定资产?
Nacos - service discovery
[JS reverse] MD5 encryption parameter cracking
C语言指针的进阶(下)
AES简单介绍