日志框架 JCL slf4j

出自本心

日志框架

日志门面

日志门面就是为了解决这个问题而出现的一种技术,日志门面是规范,其他的实现按照规范实现各自的日志框架即可,我们基于日志门面编程即可

常见的日志门面: JCL、slf4j

常见的日志实现: JUL、log4j、logback、log4j2

日志框架出现的历史顺序:

log4j –>JUL–>JCL–> slf4j –> logback –> log4j2

slf4j 日志门面

简单日志门面(Simple Logging Facade For Java) SLF4J 主要是为了给 Java 日志访问提供一套标准、规范的 API 框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架

SLF4J 是目前市面上最流行的日志门面

slf4j 的两个功能

  • 日志框架的绑定

  • 日志框架的桥接

阿里日志规约

应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架 SLF4J 中的 API。使用门面模式的日志框架,有利于维护和各个类的日志处理方法统一。

日志文件推荐至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。

应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:appName_logType_logName.log。logType 为日志类型,推荐分类有 stats/monitor/visit 等;

logName 为日志描述。这种命名的好处:通过文件名就可以知道日志文件属于哪个应用,哪种类型,有什么目的,这也有利于归类查找。

对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者占位符的方式。

避免重复打印日志,否则会浪费磁盘空间。务必在日志配置文件中设置 additivity=false。

异常信息应该包括两类:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字向上抛出。

谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 warn 记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免吧服务器磁盘撑爆,并及时删除这些观察日志。

可以使用 warn 日志级别记录用户输入参数错误的情况,避免当用户投诉时无所适从

slf4j 简单使用

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--        slf4j日志门面依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>

<!-- slf4j简单的日志实现依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.27</version>
</dependency>
  • java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class.getName());

@Test
public void testSlf4j(){

LOGGER.error("error");
LOGGER.warn("warn");
LOGGER.info("info");
LOGGER.debug("debug");
LOGGER.trace("trace");
// 使用占位符输出日志信息
LOGGER.info("{}今年{}岁了!", "xiaobo", 22);

try {
Integer result = 1 / 0;
}catch (Exception e){
LOGGER.info("这是异常",e);
}
}

slf4j 绑定其他日志实现

绑定 JUL 实现

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
<!--        slf4j日志门面依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>
<!-- slf4j绑定log4j日志实现-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.25</version>
</dependency>

绑定 log4j 实现

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--slf4j core 使用slf4j必須添加-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>
<!-- slf4j绑定log4j日志实现-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.27</version>
</dependency>
<!-- log4j日志实现依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

slf4 桥接其他日志框架

日志框架的桥接

您依赖的某些组件依赖于 SLF4J 以外的日志记录 API。您也可以假设这些组件在不久的将来不会切换到 SLF4J。为了解决这种情况,SLF4J 附带了几个桥接模块,这些模块将对 log4j,JCL 和 java.util.logging API 的调用重定向

还用 log4j 的 api 写代码,但是具体的实现给你抽离了,我们依赖了一个中间层,这个层其实是用旧的 api 操作 slf4j,而不是操作具体的实现

桥接步骤

  • 1、先去除之前老的日志框架的依赖,必须去掉

  • 2、添加 SLF4J 提供的桥接组件,这个组件就是模仿之前老的日志写了一套相同的 api,只不过这个 api 是在调用 slf4j 的 api

  • 3、为项目添加 SLF4J 的具体实现

示例

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 桥接的组件 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.27</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.27</version>
</dependency>
  • 之前名字叫 log4j 之后修改为 log4j_back
1
2
3
4
5
6
public class Log4j_back {

public void log4j(){
System.out.println("log4j");
}
}
  • slf4j
1
2
3
4
5
public interface Slf4j {

public void myLog();

}
  • slf4jimpl
1
2
3
4
5
6
7
public class Slf4j_JUL implements Slf4j {

@Override
public void myLog() {
System.out.println("slf4j");
}
}
  • log4j
1
2
3
4
5
6
7
8
9
public class Log4j {

public void log4j(){

Slf4j_JUL slf4j_jul = new Slf4j_JUL();

slf4j_jul.myLog();
}
}
  • client
1
2
3
4
5
6
7
public class Client {

public static void main(String[] args) {
Log4j log4j = new Log4j();
log4j.log4j();
}
}

slf4j 提供的桥接器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- log4j-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.27</version>
</dependency>
<!-- jul -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.27</version>
</dependency>
<!--jcl -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.27</version>
</dependency>
  • 1、jcl-over-slf4j.jar 和 slf4j-jcl.jar 不能同时部署。前一个 jar 文件将导致 JCL 将日志系统的选择委托给 SLF4J,后一个 jar 文件将导致 SLF4J 将日志系统的选择委托给 JCL,从而导致无限循环。

  • 2、log4j-over-slf4j.jar 和 slf4j-log4j12.jar 不能同时出现

  • 3、jul-to-slf4j.jar 和 slf4j-jdk14.jar 不能同时出现

  • 4、所有的桥接都只对 Logger 日志记录器对象有效,如果程序中调用了内部的配置类或者是 Appender,Filter 等对象,将无法产生效果。

JCL 日志门面

日志门面与日志实现

全称为 Jakarta Commons Logging,是 Apache 提供的一个通用日志 API

JCL 有两个基本的抽象类:Log(基本记录器)和 LogFactory(负责创建 Log 实例)

  • pom
1
2
3
4
5
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

这里的LoggerFactory.getLogger依赖的是 log4j 的日志实现

为什么要使用日志门面

面向接口开发,不再依赖具体的实现类。减少代码的耦合

项目通过导入不同的日志实现类,可以灵活的切换日志框架

统一 API,方便开发者学习和使用

统一配置便于项目日志的管理

本篇文章 仅供自己学习整理 方便阅读 参考b站某UP主 如有侵权 通知即删

你知道的越多 你不知道的越多 嘿 我是小博 带你一起看我目之所及的世界……

-------------本文结束 感谢您的阅读-------------

本文标题:日志框架 JCL slf4j

文章作者:小博

发布时间:2022年03月21日 - 20:13

最后更新:2022年10月26日 - 13:27

原始链接:https://codexiaobo.github.io/posts/1217569774/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。