https://blog.youkuaiyun.com/HarderXin/article/details/80422903
log4j
如果在我们系统中单独使用log4j的话,我们只需要引入log4j的核心包就可以了,我这里用的是:log4j-1.2.17.jar,然后在系统中使用如下代码输出日志:
-
public
class Log4jTest {
-
private
static
final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(Log4jTest.class);
-
-
public static void main(String[] args) {
-
logger.info(
"hello word");
-
}
-
}
在系统的src目录下添加依赖的配置文件:
log4j2
log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
如果在我们系统中单独使用log4j2的话,我们只需要引入log4j2的核心包就可以了,我这里用的是:log4j-api-2.7.jar和log4j-core-2.7.jar,然后在系统中使用如下代码输出日志:
-
public
class Log4j2Test {
-
private
static org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger(Log4jTest.class);
-
public static void main(String[] args) {
-
logger.info(
"hello word");
-
}
-
}
在系统的src目录下添加依赖的配置文件:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<Configuration status="info">
-
<Appenders>
-
<Console name="consoleAppender" target="SYSTEM_OUT">
-
<PatternLayout pattern="%d{DATE} %5p %c{1}:%L - %m%n" />
-
</Console>
-
-
-
</Appenders>
-
<Loggers>
-
<Root level="info">
-
<AppenderRef ref="consoleAppender" />
-
</Root>
-
</Loggers>
-
</Configuration>
关于log4j2的官方文档介绍,请查看:http://logging.apache.org/log4j/2.x/index.html关于log4j2相关配置文件,大家可以从官方文档中了解,也可以参考:http://java12345678.iteye.com/blog/2382929
log4j与log4j2的区别:
1.获取Logger的api不一样,log4j的api为org.apache.log4j.Logger,而log4j2的api为org.apache.logging.log4j.Logger2.配置方式不一样,log4j2对properties的配置支持不是很好,它的格式一般为xml格式或者yaml格式,这种格式的可读性比较好,各种配置一目了然
3.Log4j2.0基于LMAX Disruptor的异步日志在多线程环境下性能会远远优于Log4j 1.x和logback(官方数据是10倍以上)
slf4j
它仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已,所以单独的slf4j是不能工作的,必须搭配其他具体的日志实现方案,比如log4j或者log4j2,它的优势和原理可以参考:https://blog.youkuaiyun.com/winwill2012/article/details/71786004,要在系统中使用slf4j,我们需要引入的核心包为:slf4j-api-1.6.4.jar
slf4j+log4j如果我们在系统中需要使用slf4j和log4j来进行日志输出的话,我们需要引入下面的jar包:
log4j核心jar包:log4j-1.2.17.jar
slf4j核心jar包:slf4j-api-1.6.4.jar
slf4j与log4j的桥接包:slf4j-log4j12-1.6.1.jar,这个包的作用就是使用slf4j的api,但是底层实现是基于log4j
所以我们获取日志可以通过下面的代码进行:
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
-
public
class Slf4jTest {
-
private
static
final Logger logger = LoggerFactory.getLogger(Slf4jTest2.class);
-
-
-
public static void main(String[] args) {
-
logger.info(
"hello world");
-
}
-
}
slf4j+log4j2如果我们在系统中需要使用slf4j和log4j2来进行日志输出的话,我们需要引入下面的jar包:
log4j2核心jar包:log4j-api-2.7.jar和log4j-core-2.7.jar
slf4j核心jar包:slf4j-api-1.6.4.jar
slf4j与log4j2的桥接包:log4j-slf4j-impl-2.7.jar,这个包的作用就是使用slf4j的api,但是底层实现是基于log4j2
所以我们获取日志仍可以通过下面的代码进行:
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
-
public
class Slf4jTest {
-
private
static
final Logger logger = LoggerFactory.getLogger(Slf4jTest2.class);
-
-
-
public static void main(String[] args) {
-
logger.info(
"hello world");
-
}
-
}
slf4j+log4j不修改代码升级到log4j2如果我们系统中刚开始用的是slf4j和log4j,然后出于性能考虑,要升级到slf4j和log4j2,并且不需要改动任何代码的话(因为我们系统可能是一个大工程,然后基本上每个类都会有日志输出,改动代码可能牵一发而动全身),出于这个考虑,我们可以这样来进行修改:
1、删除项目中存在的Log4j1.x所必须的log4j和slf4j-log4j12等依赖,例如从我们上面做的去升级的话,需要删除log4j-1.2.17.jar和slf4j-log4j12-1.6.1.jar
2、添加log4j2和slf4j桥接包:log4j-slf4j-impl-2.7.jar替换log4j和slf4j桥接包:slf4j-log4j12-1.6.1.jar
3、如果我们在系统中使用了log4j的api去获取Logger的话:
org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(Log4jTest.class)
我们需要添加log4j-1.2-api-2.7.jar去替换log4j-1.2.17.jar4、将log4j的properties文件修改为log4j2的xml文件
然后,同样在系统中使用slf4j的方式获取日志:
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Self4jTest.class);
自定义Appender
我们系统中,根据项目的需求,可能需要自定义Appender,使日志满足我们系统中特定的需求,那么log4j和log4j2自定义Appender是不一样的:
对于log4j,我们自定义Appender可以使用如下代码,继承org.apache.log4j.AppenderSkeleton类:
-
import org.apache.log4j.AppenderSkeleton;
-
import org.apache.log4j.spi.LoggingEvent;
-
-
public
class Log4jAppender extends AppenderSkeleton {
-
-
@Override
-
public void close() {
-
-
}
-
-
@Override
-
public boolean requiresLayout() {
-
return
false;
-
}
-
-
@Override
-
protected void append(LoggingEvent logEvent) {
-
System.out.println(logEvent.getLevel() +
"---" + logEvent.getLoggerName() +
"---" + logEvent.getMessage());
-
}
-
}
然后在配置文件中使用自定义Appender:
对于log4j2,自定义Appender可以使用如下代码,继承org.apache.logging.log4j.core.appender.AbstractAppender类:
log4j.rootLogger=INFO, stdout,report log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n log4j.appender.report = com.harderxin.test.Log4jAppender
-
package com.harderxin.test;
-
-
import java.io.Serializable;
-
-
import org.apache.logging.log4j.core.Filter;
-
import org.apache.logging.log4j.core.Layout;
-
import org.apache.logging.log4j.core.LogEvent;
-
import org.apache.logging.log4j.core.appender.AbstractAppender;
-
import org.apache.logging.log4j.core.config.plugins.Plugin;
-
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
-
import org.apache.logging.log4j.core.config.plugins.PluginElement;
-
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-
import org.apache.logging.log4j.core.layout.PatternLayout;
-
-
@Plugin(name =
"MyAppender", category =
"Core", elementType =
"appender", printObject =
true)
-
public
class MyAppender extends AbstractAppender {
-
-
protected MyAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions) {
-
super(name, filter, layout, ignoreExceptions);
-
}
-
-
@Override
-
public void append(LogEvent event) {
-
final
byte[] bytes = getLayout().toByteArray(event);
-
//System.out.println(event.getLevel().intLevel() +"--->" + event.getLoggerName() + "---->" + bytes);
-
System.out.println(
new String(bytes) +
"aslkdjkas");
-
}
-
-
// 下面这个方法可以接收配置文件中的参数信息
-
@PluginFactory
-
public static MyAppender createAppender(@PluginAttribute("name") String name,
-
@PluginElement("Filter") final Filter filter,
-
@PluginElement("Layout") Layout<? extends Serializable> layout,
-
@PluginAttribute("ignoreExceptions") boolean ignoreExceptions) {
-
if (name ==
null) {
-
LOGGER.error(
"No name provided for MyCustomAppenderImpl");
-
return
null;
-
}
-
if (layout ==
null) {
-
layout = PatternLayout.createDefaultLayout();
-
}
-
return
new MyAppender(name, filter, layout, ignoreExceptions);
-
}
-
}
然后在配置文件中使用自定义Appender:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<Configuration status="info" packages="com.harderxin.test">
-
<Properties>
-
<Property name="LOG_SUFFIX">${sys:log4j2.suffix}
</Property>
-
<Property name="LOG_HOME">logs
</Property>
-
</Properties>
-
-
<Appenders>
-
<Console name="consoleAppender" target="SYSTEM_OUT">
-
<PatternLayout pattern="%d{DATE} %5p %c{1}:%L - %m%n" />
-
</Console>
-
<RollingRandomAccessFile name="rollingRandomAccessFileAppender"
-
immediateFlush=
"true"
fileName=
"${LOG_HOME}/sensor${LOG_SUFFIX}.log"
-
filePattern=
"${LOG_HOME}/sensor${LOG_SUFFIX}.log.%i">
-
<PatternLayout>
-
<Pattern>%d{DATE} %5p %c{1}:%L - %m%n
</Pattern>
-
</PatternLayout>
-
<Policies>
-
<SizeBasedTriggeringPolicy size="1 KB" />
-
</Policies>
-
<DefaultRolloverStrategy max="13" />
-
</RollingRandomAccessFile>
-
<MyAppender name="myAppender">
</MyAppender>
-
</Appenders>
-
<Loggers>
-
<Root level="info">
-
<AppenderRef ref="consoleAppender" />
-
<AppenderRef ref="rollingRandomAccessFileAppender" />
-
<AppenderRef ref="myAppender" />
-
</Root>
-
</Loggers>
-
</Configuration>
我们在运行程序的时候,可能会报如下错误信息:
2018-05-23 17:25:29,178 main ERROR Appenders contains an invalid element or attribute "MyAppender"
2018-05-23 17:25:29,188 main ERROR Unable to locate appender "myAppender" for logger config "root"
这是因为我们自定义Appender在配置文件中找不到,我们程序在初始化的时候没有将我们自定义的Appender加入到log4j2的相关目录下导致的,所以我们需要在配置文件中配置我们自定义Appender的包名:
<Configuration status="info" packages="com.harderxin.test">
对于log4j和log4j2自定义Appender是不一样的,log4j是继承自log4j的核心包中的类:org.apache.log4j.AppenderSkeleton,而log4j2是继承自它的核心包中的类org.apache.logging.log4j.core.appender.AbstractAppender,所以如果系统要进行从log4j升级到log4j2的话,如果有自定义的Appender,我们需要重新修改代码,让它兼容log4j2,这一点在升级的时候需要考虑,还有我们需要考虑的是系统中用到的其他jar包是否也用到了log4j2不支持的log4j的功能,所以升级的时候要慎重,不然升级完系统还是会存在问题。
在配置文件中使用变量
有时候我们需要在配置文件中的一些变量,通过后台代码去进行动态设置,比如日志文件的名称等等,我们可以在配置文件中通过${log4j.suffix}的方式进行参数设置
例如log4j:
log4j.appender.file.rollingPolicy.ActiveFileName=logs/sensor${log4j.suffix}.log
log4j2:
-
<Properties>
-
<Property name="LOG_SUFFIX">${sys:log4j2.suffix}
</Property>
-
<Property name="LOG_HOME">logs
</Property>
-
</Properties>
然后我们在后台使用System.setProperties的方式给变量赋值:
System.setProperty("log4j2.suffix", "aao0506");
在自定义目录下加载配置文件
有时候我们的配置文件不一定是放在src目录下,也可能是放在我们系统自定义的一个目录下,比如conf,那么我们系统在初始化的时候如何加载这些配置文件:
对于log4j,我们可以使用如下代码:
org.apache.log4j.PropertyConfigurator.configure("conf/log4j.properties");
对于log4j2,我们可以使用如下代码:
System.setProperty("log4j.configurationFile", "conf/log4j2.properties");
但是在做测试的时候发现log4j2上面的代码加载不起作用,还是会报下面的错误信息:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
所以可以使用下面的加载方式:
-
public static void loadLogConfiguration() {
-
org.apache.logging.log4j.core.config.ConfigurationSource source;
-
try {
-
source =
new org.apache.logging.log4j.core.config.ConfigurationSource(
-
new FileInputStream(
"conf/log4j2.xml"));
-
org.apache.logging.log4j.core.config.Configurator.initialize(
null, source);
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
好了,关于日志的介绍就到这里了,上面涉及到的jar包,大家可以到官网去下载,也可以到我的资源库去统一下载https://download.youkuaiyun.com/download/harderxin/10433056
log4j相关jar包区别说明参考:http://xfhnever.com/2015/09/20/log-java-2/