日志门面
当我们的系统变得更加复杂的时候,我们的日志就容易发生混乱。随着系统开发的进行,可能会更新不同的日志框架,造成当前系统中存在不同的日志依赖,让我们难以统一的管理和控制。就算我们强制要求所有的模块使用相同的日志框架,系统中也难以避免使用类似spring、mybatis等其他的第三方框架,他们依赖于我们规定不同的框架,而且他们自身的日志系统就有着不一致性,依然会出来日志体系的混乱。
所以我们需要借鉴JDBC的思想,为日志系统也提供一套门面,那么我们就可以面向这些接口规范来开发,避免了直接依赖具体的日志框架。这样我们的系统在日志中,就存在了日志的门面和日志的实现。
常见的日志门面:
JCL、slf4j
常见的日志实现:
JUL、log4j、logback、log4j2
日志门面和日志门面的关系:
日志框架出现的历史顺序:
log4j->JUL->JCL->slf4j->logback->log4j2
SLF4J的使用
简单的日志门面(Simple Logging Facade For Java)SLF4J主要是为了给Java日志访问提供一个标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。
官方网站:http://www.slf4j.org/
SLFJ是目前市场上最流行的日志门面。现在的项目中,基本上都是使用SLF4J作为我们的日志系统。
SLF日志门面主要提供两大功能:
日志框架的绑定
日志框架的桥接
SLF4J入门
- 添加依赖
<!--slf4j日志门面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.31</version>
</dependency>
<!--slf4j内置的简单实现-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.31</version>
</dependency>
- 代码块
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4JTest {
public static final Logger LOGGER = LoggerFactory.getLogger(Slf4JTest.class);
@Test
public void testOne() {
// 日志输出
LOGGER.error("error");
LOGGER.warn("warn");
// 默认级别
LOGGER.info("info");
LOGGER.debug("debug");
LOGGER.trace("trace");
// 使用占位符输出日志信息
String name = "zyifan";
Integer age = 18;
LOGGER.info("用户信息:{},{}", name, age);
// 输出系统的异常信息
try {
int i = 1 / 0;
} catch (Exception exception) {
LOGGER.error("出现异常", exception);
}
}
}
输出结果
[main] ERROR com.itcast.Slf4JTest - error
[main] WARN com.itcast.Slf4JTest - warn
[main] INFO com.itcast.Slf4JTest - info
[main] INFO com.itcast.Slf4JTest - 用户信息:zyifan,18
[main] ERROR com.itcast.Slf4JTest - 出现异常
java.lang.ArithmeticException: / by zero
at com.itcast.Slf4JTest.testOne(Slf4JTest.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
绑定日志的实现(Binding)
如前所述,SLF4J支持各种日志框架。SLF4J发行版附带了几个成为“SLF4J绑定”的jar文件,每个文件对应一个受支持的框架。
使用slf4j的日志绑定流程
- 添加slf4j-api的依赖
- 使用slf4j的API在项目中进行统一的日志记录
- 绑定具体的日志实现框架
1. 绑定了已经实现了slf4j的日志框架,直接添加对应依赖
2. 绑定没有是新slf4j的日志框架,先添加日志的适配器,再添加实现类的依赖 - slf4j有且仅有一个日志实现框架的绑定(如果出现多个默认使用第一个依赖日志实现)
通过maven引入常见的日志实现框架:
<!--slf4j日志门面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.31</version>
</dependency>