JUL:JDK中的日志记录工具,也常称为JDKLog、jdk-logging。
LOG4J1:一个具体的日志实现框架。
LOG4J2:一个具体的日志实现框架,是LOG4J1的下一个版本。
LOGBACK:一个具体的日志实现框架,但其性能更好。
JCL:一个日志门面,提供统一的日志记录接口,也常称为commons-logging。
SLF4J:一个日志门面,与JCL一样提供统一的日志记录接口,可以方便地切换看具体的实现框架。
注意:JUL、LOG4J1、LOG4J2、LOGBACK是日志实现框架,而JCL、SLF4J是日志实现门面(接口)。
在实际的日志转换过程中,SLF4J其实是充当一个中介的角色。例如当我们一个项目原来是使用LOG4J进行日志记录,但是我们要换成LogBack进行日志记录。
此时我们需要先将LOG4J转换成SLF4J日志系统,再从SLF4J日志系统转成LogBack日志系统。
从日志框架转SLF4J(如下图)
jul-to-slf4j:jdk-logging到slf4j的桥梁
log4j-over-slf4j:log4j1到slf4j的桥梁
jcl-over-slf4j:commons-logging到slf4j的桥梁
从SLF4J转具体的日志框架(如下图)
slf4j-jdk14:slf4j到jdk-logging的桥梁
slf4j-log4j12:slf4j到log4j1的桥梁
log4j-slf4j-impl:slf4j到log4j2的桥梁
logback-classic:slf4j到logback的桥梁
slf4j-jcl:slf4j到commons-logging的桥梁
例如我们一开始使用的是 Log4J 日志框架,现在我们希望转成 LogBack 框架,那么我们首先需要加入 log4j-over-slf4j.jar 将 Log4J 转成 SLF4J,之后再加入 logback-classic.jar 将 SLF4J 转成 LogBack。
Logger logger = Logger.getLogger("JDKLog");
logger.info("Hello World");
在前几年的系统中经常使用log4j,所以现在很多公司需要将log4j切换到logback。肯定是不可能一行行修改的,需要通过下面的slf4j适配器进行转换。
使用姿势
<!-- Log4J -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
Console>
Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
Root>
Loggers>
Configuration>
其中节点的 level 属性表示输出的最低级别。
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/****
** Log4J Demo
**/
public class Log4jLog {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(Log4jLog.class);
logger.debug("Debug Level");
logger.info("Info Level");
logger.warn("Warn Level");
logger.error("Error Level");
}
}
10:16:08.279 [main] INFO com.chanshuyi.Log4jLog - Info Level
10:16:08.280 [main] WARN com.chanshuyi.Log4jLog - Warn Level
10:16:08.280 [main] ERROR com.chanshuyi.Log4jLog - Error Level
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
Console>
Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
Root>
Loggers>
Configuration>
但 Log4J 本身也存在一些缺点,比如不支持使用占位符,不利于代码阅读等缺点。但是相比起 JDKLog,Log4J 可以说是非常好的日志记录框架了。
LogBack 其实可以说是 Log4J 的进化版,因为它们两个都是同一个人(Ceki Gülcü)设计的开源日志组件。LogBack 除了具备 Log4j 的所有优点之外,还解决了 Log4J 不能使用占位符的问题。
使用 LogBack 需要首先引入依赖:
ch.qos.logback
logback-classic
1.1.7
配置 logback.xml 配置文件:
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
LogBack 的日志级别区分可以细分到类或者包,这样就可以使日志记录变得更加灵活。之后在类文件中引入Logger类,并进行日志记录:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/****
** LogBack Demo
**/
public class LogBack {
static final Logger logger = LoggerFactory.getLogger(LogBack.class);
public static void main(String[] args) {
logger.trace("Trace Level.");
logger.debug("Debug Level.");
logger.info("Info Level.");
logger.warn("Warn Level.");
logger.error("Error Level.");
}
}
输出结果:
14:34:45.747 [main] TRACE com.chanshuyi.LogBack - Trace Level.
14:34:45.749 [main] DEBUG com.chanshuyi.LogBack - Debug Level.
14:34:45.749 [main] INFO com.chanshuyi.LogBack - Info Level.
14:34:45.749 [main] WARN com.chanshuyi.LogBack - Warn Level.
14:34:45.749 [main] ERROR com.chanshuyi.LogBack - Error Level.
LogBack 解决了 Log4J 不能使用占位符的问题,这使得阅读日志代码非常方便。除此之外,LogBack 比 Log4J 有更快的运行速度,更好的内部实现。并且 LogBack 内部集成了 SLF4J 可以更原生地实现一些日志记录的实现。
因为在实际的项目应用中,有时候可能会从一个日志框架切换到另外一个日志框架的需求,这时候往往需要在代码上进行很大的改动。为了避免切换日志组件时要改动代码,这时候一个叫做 SLF4J(Simple Logging Facade for Java,即Java简单日志记录接口集)的东西出现了。
SLF4J(Simple Logging Facade for Java,即Java简单日志记录接口集)是一个日志的接口规范,它对用户提供了统一的日志接口,屏蔽了不同日志组件的差异。这样我们在编写代码的时候只需要看 SLF4J 这个接口文档即可,不需要去理会不同日之框架的区别。而当我们需要更换日志组件的时候,我们只需要更换一个具体的日志组件Jar包就可以了。
而整合 SLF4J 和日志框架使用也是一件很简单的事情。
SLF4J + JDKLog 需要在 Maven 中导入以下依赖包:
org.slf4j
slf4j-api
1.7.21
org.slf4j
slf4j-jdk14
1.7.21
编写测试类:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/****
** SLF4J + JDKLog
**/
public class Slf4jJDKLog {
final static Logger logger = LoggerFactory.getLogger(Slf4jJDKLog.class);
public static void main(String[] args) {
logger.trace("Trace Level.");
logger.info("Info Level.");
logger.warn("Warn Level.");
logger.error("Error Level.");
}
}
输出结果:
七月 15, 2016 3:30:02 下午 com.chanshuyi.slf4j.Slf4jJDKLog main
信息: Info Level.
七月 15, 2016 3:30:02 下午 com.chanshuyi.slf4j.Slf4jJDKLog main
警告: Warn Level.
七月 15, 2016 3:30:02 下午 com.chanshuyi.slf4j.Slf4jJDKLog main
严重: Error Level.
需要依赖的 Jar 包:slf4j-api.jar、slf4j-412.jar、log4j.jar,导入Maven依赖:
org.slf4j
slf4j-api
1.7.21
org.slf4j
slf4j-log4j12
1.7.21
log4j
log4j
1.2.17
配置 log4j.xml 文件:
我们还是用上面的代码,无需做改变,运行结果为:
[15 16:04:06,371 DEBUG] [main] slf4j.SLF4JLog - Debug Level.
[15 16:04:06,371 INFO ] [main] slf4j.SLF4JLog - Info Level.
[15 16:04:06,371 WARN ] [main] slf4j.SLF4JLog - Warn Level.
[15 16:04:06,371 ERROR] [main] slf4j.SLF4JLog - Error Level.
导入依赖:
org.slf4j
slf4j-api
1.7.21
ch.qos.logback
logback-classic
1.1.7
ch.qos.logback
logback-core
1.1.7
配置 logback.xml 文件:
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
我们还是用上面的代码,无需做改变,运行结果为:
16:08:01.040 [main] TRACE com.chanshuyi.slf4j.SLF4JLog - Trace Level.
16:08:01.042 [main] DEBUG com.chanshuyi.slf4j.SLF4JLog - Debug Level.
16:08:01.043 [main] INFO com.chanshuyi.slf4j.SLF4JLog - Info Level.
16:08:01.043 [main] WARN com.chanshuyi.slf4j.SLF4JLog - Warn Level.
16:08:01.043 [main] ERROR com.chanshuyi.slf4j.SLF4JLog - Error Level.
经过上面的介绍,相信大家对 Java 常用的日志框架都有了一定认识。
那么在实际使用中到底选择哪种日志框架合适呢?
按笔者理解,现在最流的日志框架解决方案莫过于SLF4J + LogBack。原因有下面几点:
从上面几点来看,SLF4J + LogBack是一个较好的选择。
LogBack 被分为3个组件:logback-core、logback-classic 和 logback-access。
LogBack的日志记录数据流是从 Class(Package)到 Logger,再从Logger到Appender,最后从Appender到具体的输出终端。
LogBack配置文件可以分为几个节点,其中 Configuration 是根节点,Appender、Logger、Root是Configuration的子节点。
是的子节点,是负责写日志的组件。appender有两个必要属性name、class 。name指定appender的名称,class指定appender的全限定名
class,主要包括:
ConsoleAppender
把日志添加到控制台,有如下节点:
%date [%thread] %-5level %logger - %message%newline
FileAppender
把日志添加到文件,有如下节点:
logs/debug.log
%date [%thread] %-5level %logger - %message%newline
rollingFileAppender
滚动纪录文件,先将日志记录到指定文件,当符合某种条件时,将日志记录到其他文件,有如下节点:
rollingPolicy
logs/error.log
errorFile.%d{yyyy-MM-dd}.log
30
150
%d [%p] %-5level %logger - %msg%newline
logger是的子节点,来设置某一个包或者具体的某一个类的日志打印级别,以及指定。logger仅有一个name属性,两个可选属性 level/addtivity。
可以包含零个或多个元素,表示这个appender将会添加到logger。
INFO
ACCEPT
DENY
logs/info.log
infoFile.%d{yyyy-MM-dd}.log
30
150
%d [%p] %-5level %logger - %msg%newline
元素配置根logger。该元素有一个level属性,没有name属性,因为已经被命名 为root。Level属性的值大小写无关,其值为下面其中一个字符串:TRACE、DEBUG、INFO、 WARN、ERROR、ALL 和 OFF。如果 root 元素没 有引用任何 appender,就会失去所有 appender。
INFO
ACCEPT
DENY
logs/info.log
infoFile.%d{yyyy-MM-dd}.log
30
150
%d [%p] %-5level %logger - %msg%newline
logs/debug.log
debugFile.%d{yyyy-MM-dd}.log
30
150
%d [%p] %-5level %logger - %msg%newline
logs/error.log
errorFile.%d{yyyy-MM-dd}.log
30
150
%d [%p] %-5level %logger - %msg%newline
级别过滤器(LevelFilter)
LevelFilter 根据记录级别对记录事件进行过滤。如果事件的级别等于配置的级别,过滤 器会根据 onMatch 和 onMismatch 属性接受或拒绝事件。下面是个配置文件例子:
INFO
ACCEPT
DENY
%-4relative [%thread] %-5level %logger{30} - %msg%n
临界值过滤器(ThresholdFilter)
ThresholdFilter过滤掉低于指定临界值的事件。
INFO
%-4relative [%thread] %-5level %logger{30} - %msg%n
求值过滤器(EvaluatorFilter)
评估是否符合指定的条件
message.contains("hello")
NEUTRAL
DENY
%-4relative [%thread] %-5level %logger{30} - %msg%n
匹配器(Matchers)
odd
statement [13579]
odd.matches(formattedMessage)
NEUTRAL
DENY
%-4relative [%thread] %-5level %logger{30} - %msg%n
下面是一个我常用的logback.xml配置文件,供大家参考:
%d{yyyy-MM-dd HH:mm:ss} [%level] - %m%n
logs/error.log
%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n
ERROR
ACCEPT
DENY
error.%d{yyyy-MM-dd}.log.zip
30
logs/info.log
%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n
INFO
ACCEPT
DENY
info.%i.log
1
3
5MB
logs/debug.log
%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n
DEBUG
ACCEPT
DENY
debug-%d{yyyy-MM-dd}.%i.log
100MB
logs/sum.log
%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n
INFO
debug-%d{yyyy-MM-dd}.%i.log
100MB
在实际的日志转换过程中,SLF4J其实是充当了一个中介的角色。例如当我们一个项目原来是使用LOG4J进行日志记录,但是我们要换成LogBack进行日志记录。
此时我们需要先将LOG4J转换成SLF4J日志系统,再从SLF4J日志系统转成LogBack日志系统。
https://www.cnblogs.com/chanshuyi/p/something_about_java_log_framework.html