Java Log4j和Log4j2的区别
一、核心JAR包
log4j核心包:log4j:log4j:[version]
而log4j2的核心包有2个:
org.apache.logging.log4j:log4j-core:[version]
org.apache.logging.log4j:log4j-api:[version]
二、配置文件
log4j:通过一个log4j.properties的文件作为主配置文件
以下是一个输出到控制台的例子
log4j.rootLogger=INFO,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%p] [%thread] [%c] >>> %m%n
%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2011-10-18 22:10:28,921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%: 输出一个"%"字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行
log4j2:采用的是.xml,.json或者.jsn这种方式来做,比如log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="log4j2: %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
至于更加深入的配置分析,可以查看各自的文档
三、调用方式
log4j:
import org.apache.log4j.Logger;
private static final Logger logger = Logger.getLogger(App.class);
log4j2:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
private static final Logger logger = LogManager.getLogger(App.class);
四、关于org.slf4j
这个只是一个日志门面模式,方面我们在各种不同的日志实现中切换,而不需要修改写日志的代码,如果org.slf4j找不到实现,
会抛出Failed to load class org.slf4j.impl.StaticLoggerBinder(see:https://www.slf4j.org/codes.html#StaticLoggerBinder)
引用库:
implementation 'org.slf4j:slf4j-api:[version]'
implementation 'org.slf4j:slf4j-log4j12:[version]'
调用方式
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(App.class);
org.slf4j使用log4j2,我们仅仅修改引用的包即可,代码不需要变更
implementation 'org.slf4j:slf4j-api:1.7.26'
implementation 'org.apache.logging.log4j:log4j-core:2.12.0'
implementation 'org.apache.logging.log4j:log4j-api:2.12.0'
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.12.0'
日志库冲突问题
我们项目使用了logback,但是其他包又引入了log4j2,这样会导致日志实现冲突,SLF4J: Class path contains multiple SLF4J bindings.(see:http://www.slf4j.org/codes.html#multiple_bindings)
解决方式:去除其他日志库,确保只有一个日志库实现
注意:即使存在多个绑定,slf4j也会选择一个日志框架/实现并与之绑定。slf4j选择绑定的方式由jvm决定,对于所有实际用途,都应视为随机的。从1.6.6版开始,slf4j将命名它实际绑定到的框架/实现类。