slf4j与log4j、log4j2

slf4j与log4j、log4j2nbsp nbsp 最近公司项目系统需要将日志从 log4j slf4j 升级为 log4j2 然后彻彻底底的把它们研究了一遍 在网上查找相关资源 发现并没有一篇文章能够很完整的把它们之间的关联和区别写出来 所以我在这里做一个总结 log4j nbsp nbsp 如果在我们系统中单独使用 log4j 的话 我们只需要引入 log4j 的核心包就可以了 我这里用的是 log4j 1 2 17 jar 然后在系统中使用如下代码输出日志 pu

   
最近公司项目系统需要将日志从log4j+slf4j升级为log4j2,然后彻彻底底的把它们研究了一遍,在网上查找相关资源,发现并没有一篇文章能够很完整的把它们之间的关联和区别写出来,所以我在这里做一个总结。

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目录下添加依赖的配置文件:

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的话,我们只需要引入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目录下添加依赖的配置文件:

 
       
       
        
         
          
         
        
        
         
          
         
        
      

关于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.Logger
2.配置方式不一样,log4j2对properties的配置支持不是很好,它的格式一般为xml格式或者yaml格式,这种格式的可读性比较好,各种配置一目了然
3.Log4j2.0基于LMAX Disruptor的异步日志在多线程环境下性能会远远优于Log4j 1.x和logback(官方数据是10倍以上)

slf4j

    它仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已,所以单独的slf4j是不能工作的,必须搭配其他具体的日志实现方案,比如log4j或者log4j2,它的优势和原理可以参考:https://blog.csdn.net/winwill2012/article/details/,要在系统中使用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.jar
4、将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:

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

对于log4j2,自定义Appender可以使用如下代码,继承org.apache.logging.log4j.core.appender.AbstractAppender类:

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 
              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 
              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:

 
               
               
                
                
                  ${sys:log4j2.suffix} 
                 
                
                  logs 
                 
                
                
                 
                  
                 
                 
                  
                  
                    %d{DATE} %5p %c{1}:%L - %m%n 
                   
                  
                  
                   
                  
                  
                 
                 
                
                
                 
                  
                  
                  
                 
                
              

我们在运行程序的时候,可能会报如下错误信息:

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的包名:

 
              

对于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:

 
               
               
                 ${sys:log4j2.suffix} 
                
               
                 logs 
                
              

然后我们在后台使用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.csdn.net/download/harderxin/10433056

log4j相关jar包区别说明参考:http://xfhnever.com/2015/09/20/log-java-2/













版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205089.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午6:50
下一篇 2026年3月19日 下午6:50


相关推荐

  • adminlte ajax,AdminLTE

    adminlte ajax,AdminLTEReminder!AdminLTEusesallofBootstrap3components.It’sagoodstarttoreviewtheBootstrapdocumentationtogetanideaofthevariouscomponentsthatthisdocumentationdoesnotcover.Tip!Ifyoug…

    2022年7月27日
    7
  • linux终端使用gcc为什么显示未找到命令_linux下编译c程序

    linux终端使用gcc为什么显示未找到命令_linux下编译c程序ai0909于2011-11-0114:21:05发表:{:2_97:}itank于2011-02-2715:26:44发表:你试试gcchello.c-ohellowusmliao于2010-11-2519:46:00发表:求答案vfdff于2010-11-1412:29:29发表:使用whichgcc查看,如果没有则添加环境变量troy268于2…

    2022年10月13日
    5
  • android手机指纹识别_屏下指纹缺点

    android手机指纹识别_屏下指纹缺点手机科技发展到目前阶段,对于指纹解锁技术已经到第二阶段了,第一阶段有三种指纹解锁方式:正面、侧面、背面,而第二阶段那就是目前还处于上阵新兵状态的屏下指纹,这里我就我个人使用的情况,来谈一下这几种指纹解锁的优劣势吧。一、正面指纹解锁,代表机型iPhone如果我没有记错的话,虽然不是第一个用,但苹果的指纹解锁是从iPhone5S开始,并流行起来的,并且从此就一发不可收拾,我是从iPhone6SP开…

    2022年8月10日
    8
  • 不是单组分组函数

    不是单组分组函数问题:一:SELECT tablespace_name, SUM(bytes) freeFROM dba_free_space不是单组分组函数原因: 1、如果程序中使用了分组函数,则有两种情况可以使用:程序中存在group by,并指定了分组条件,这样可以将分组条件一起查询出来改为:  SELECT tablespace_name, SUM(bytes) freeFROM dba_free_spa…

    2022年6月30日
    29
  • ipvsadm 常用命令

    ipvsadm 常用命令1 查看是否支持 ipvs nbsp modprobe l grepipvs2 ipvsadm 命令详解 C 清除表中所有的记录 Aadd service 在服务器列表中新添加一条新的虚拟服务器记录 t 表示为 tcp 服务 u 表示为 udp 服务 sscheduler 使用的调度算法 rr wrr lc wlc lblb lblcr dh sh

    2026年3月18日
    1
  • 除了p站还有哪些站_p站以外的

    除了p站还有哪些站_p站以外的说p站,估计不知道的人已经很少了,不过今天搜罗君要说是,除了p站还有哪些站?我盲猜,应该很多人思考过这个问题了~咱们按照英文字母顺序ABCD···XYZ来说1.A站AcFun,中国第…

    2026年4月13日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号