精华内容
下载资源
问答
  • 主要介绍了Java日志框架之logback使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 日志记录是应用程序运行中必不可少的一部分。这篇文章主要介绍了浅谈Java日志框架slf4j作用及其实现原理,SLF4J是一个日志框架抽象层,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Java日志框架

    2021-02-24 17:16:32
    眼下java应用日志收集都是採用日志框架(slf4j、apachecommonslogging)+日志系统(log4j、log4j2、LogBack、JUL等)的方式。日志框架:提供日志调用的接口,实际的日志输出托付给日志系统实现。JCL...
  • java日志框架

    2015-12-06 21:30:57
    log4j和logback的helloworld以及与spring等的整合使用
  • java日志框架探秘

    2021-02-24 17:17:06
    目前市面上已经存在的日志框架有log4j,log4j2,logback,java.util.logging。然而,现在主流的这几个日志框架基本都是基于实现类编程,而非接口编程,暴露了一些无关紧要的信息给用户,这种耦合没有必要,还有当应用...
  • 在使用Java的时候,想必大家或多或少都对我们使用的日志api有所疑惑,为什么网上有那么多日志框架可以选择,但是我们平时打印日志的时候用的却基本都是log.info("xxx")这种形式,为什么在我们的pom.xml中要配置那么...


    在使用Java的时候,想必大家或多或少都对我们使用的日志api有所疑惑,为什么网上有那么多日志框架可以选择,但是我们平时打印日志的时候用的却基本都是 log.info("xxx")这种形式,为什么在我们的 pom.xml中要配置那么多的日志依赖,或者有时还需要主动将某些第三方依赖里面的日志依赖给主动去掉,相信读完本篇文章,你对这些问题的疑惑将一一解除。

    一、日志

    生活中的日志是记录你生活点点滴滴,让它把你内心的世界表露出来,更好的诠释自己的内心世界,而电脑里的日志可以是有价值的信息宝库,也可以是毫无价值的数据泥潭。

    以上的介绍你百度百科对日志这个概念的介绍,想必阅读本篇文章的人都对日志是有一定的了解的了,所以本文也不做过多的赘述,我们直接进入后面对日志框架以及门面的介绍

    二、常见日志框架

    在Java领域,常见的日志框架有JUL、Log4j、Logback、log4j2

    历史

    log4j可以当之无愧地说是Java日志框架的元老,1999年发布首个版本,2012年发布最后一个版本,2015年正式宣布终止,至今还有无数的系统在使用log4j,甚至很多新系统的日志框架选型仍在选择log4j。

    然而老的不等于好的,在IT技术层面更是如此。尽管log4j有着出色的历史战绩,但早已不是Java日志框架的最优选择。

    在log4j被Apache Foundation收入门下之后,由于理念不合,log4j的作者Ceki离开并开发了slf4j和logback。

    slf4j因其优秀的性能和理念很快受到了广泛欢迎,2016年的统计显示,github上的热门Java项目中,slf4j是使用率第二名的类库(第一名是junit)。

    logback则吸取了log4j的经验,实现了很多强大的新功能,再加上它和slf4j能够无缝集成,也受到了欢迎。

    在这期间,Apache Logging则一直在关门憋大招,log4j2在beta版鼓捣了几年,终于在2014年发布了GA版,不仅吸收了logback的先进功能,更通过优秀的锁机制、LMAX Disruptor、"无垃圾"机制等先进特性,在性能上全面超越了log4j和logback。

    好了。那么上面我们讲完了框架们的历史,下面我们正式对这些日志框架进行基本的介绍

    各大框架介绍

    JUL

    在这里插入图片描述
    j.u.l是java.util.logging包的简称,是JDK在1.4版本中引入的Java原生日志框架。Java Logging API提供了七个日志级别用来控制输出。这七个级别分别是:SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST。

    Log4j(1999-2015)

    Log4j 是一种非常流行的日志框架,由Ceki Gülcü首创,之后将其开源贡献给 Apache 软件基金会。

    通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

    Log4j也有七种日志级别:OFF、FATAL、ERROR、WARN、INFO、DEBUG和TRACE。

    log4j可以说是当之无愧的Java日志框架的元老,1999年发布首个版本,2012年发布最后一个版本,2015年正式宣布终止,至今还有无数的系统在使用log4j,甚至很多新系统的日志框架选型仍在选择log4j。

    在log4j被Apache Foundation收入门下之后,由于理念不合,log4j的作者Ceki离开并开发了slf4j和logback。

    Logback(2006-?)

    Logback也是一个很成熟的日志框架,从06年开始第一个版本,迭代至今也十几年了。不过logback最近一个稳定版本还停留在 2017 年,好几年都没有更新;logback的兄弟 Slf4j 最近一个稳定版也是2017年,有点凉凉的意思。其中Logback、Log4j、Slf4j都是出自同一个人之手

    logback 主要分为3个模块:

    • logback-core:核心代码模块
    • logback-classic:log4j的一个改良版本,同时实现了slf4j的接口,这样你如果之后要切换其他日志组件也是一件很容易的事
    • logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

    Log4j2

    前面介绍过Log4j,这里要单独介绍一下Log4j2,之所以要单独拿出来说,而没有和Log4j放在一起介绍,是因为作者认为,Log4j2已经不仅仅是Log4j的一个升级版本了,而是从头到尾被重写的,log4j2 是 log4j 1.x 的升级版,其参考了 logback 的一些优秀的设计,并且修复了一些问题,其实可以认为这其实就是完全不同的两个框架。

    在现在我们单独使用时:其jar包分别是

    • org.apache.logging.log4j » log4j-api-2.x.x.jar(api包,类似于日志门面)
    • org.apache.logging.log4j » log4j-core-2.x.x.jar(具体实现)
      注意其前缀是log4j而不是log4j2

    上面我们并没有对这些日志框架进行非常详细的使用介绍,感兴趣的同学们可以自行查询相关资料进一步了解,这里我们仅提供这些日志框架的对比信息

    Logback与Log4j2对比

    在以上介绍的日志框架中,logback和log4j2都宣称自己是log4j的后代,一个是出于同一个作者,另一个则是在名字上根正苗红。由于Log4j Apache已经不再更新,所以我们现在使用的日志框架,基本就是在logback以及log4j2之中选择一个。

    撇开血统不谈,我们比较一下log4j2和logback:

    • log4j2比logback更新:log4j2的GA版在2014年底才推出,比logback晚了好几年,这期间log4j2确实吸收了slf4j和logback的一些优点(比如日志模板),同时应用了不少的新技术
    • 由于采用了更先进的锁机制和LMAX Disruptor库,log4j2的性能优于logback,特别是在多线程环境下和使用异步日志的环境下
    • 二者都支持Filter(应该说是log4j2借鉴了logback的Filter),能够实现灵活的日志记录规则(例如仅对一部分用户记录debug级别的日志)
    • 二者都支持对配置文件的动态更新
    • 二者都能够适配slf4j,logback与slf4j的适配应该会更好一些,毕竟省掉了一层适配库(同一作者)
    • logback能够自动压缩/删除旧日志
    • logback提供了对日志的HTTP访问功能
    • log4j2实现了“无垃圾”和“低垃圾”模式。简单地说,log4j2在记录日志时,能够重用对象(如String等),尽可能避免实例化新的临时对象,减少因日志记录产生的垃圾对象,减少垃圾回收带来的性能下降

    关于它们两者的性能对比,有兴趣的大家可以参阅这篇文章

    三、日志门面

    前面介绍了四种日志框架,也就是说,我们想要在应用中打印日志的时候,可以使用以上四种类库中的任意一种。比如想要使用Log4j,那么只要依赖Log4j的jar包,配置好配置文件并且在代码中使用其API打印日志就可以了。

    不知道有多少人看过《阿里巴巴Java开发手册》,其中有一条规范做了『强制』要求:

    在这里插入图片描述

    说好了以上四种常用的日志框架是给Java应用提供的方便进行记录日志的,那为什么又不让在应用中直接使用其API呢?这里面推崇使用的SLF4J是什么呢?所谓的门面模式又是什么东西呢?

    什么是日志门面

    日志门面,是门面模式的一个典型的应用。

    门面模式(Facade Pattern),也称之为外观模式,其核心为:外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用,这里我们也可以抽象地理解为Java的接口。

    在这里插入图片描述

    就像前面介绍的几种日志框架一样,每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性。

    为了解决这个问题,就是在日志框架和应用程序之间架设一个沟通的桥梁,对于应用程序来说,无论底层的日志框架如何变,都不需要有任何感知。只要门面服务做的足够好,随意换另外一个日志框架,应用程序不需要修改任意一行代码,就可以直接上线。

    在软件开发领域有这样一句话:计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。而门面模式就是对于这句话的典型实践。

    为什么需要日志门面

    前面提到过一个重要的原因,就是为了在应用中屏蔽掉底层日志框架的具体实现。这样的话,即使有一天要更换代码的日志框架,只需要修改jar包,最多再改改日志输出相关的配置文件就可以了。这就是解除了应用和日志框架之间的耦合。

    有人或许会问了,如果我换了日志框架了,应用是不需要改了,那日志门面不还是需要改的吗?

    要回答这个问题,我们先来举一个例子,再把门面模式揉碎了重新解释一遍。

    日志门面就像饭店的服务员,而日志框架就像是后厨的厨师。对于顾客这个应用来说,我到饭店点菜,我只需要告诉服务员我要一盘番茄炒蛋即可,我不关心后厨的所有事情。因为虽然主厨从把这道菜称之为『番茄炒蛋』A厨师换成了把这道菜称之为『西红柿炒鸡蛋』的B厨师。但是,顾客不需要关心,他只要下达『番茄炒蛋』的命令给到服务员,由服务员再去翻译给厨师就可以了。

    所以,对于一个了解了”番茄炒蛋的多种叫法”的服务员来说,无论后厨如何换厨师,他都能准确的帮用户下单。

    同理,对于一个设计的全面、完善的日志门面来说,他也应该是天然就兼容了多种日志框架的。所以,底层框架的更换,日志门面几乎不需要改动。

    以上,就是日志门面的一个比较重要的好处——解耦。

    常用日志门面

    介绍过了日志门面的概念和好处之后,我们看看Java生态体系中有哪些好的日志门面的实现可供选择。

    Slf4j

    Java简易日志门面(Simple Logging Facade for Java,缩写SLF4J),是一套包装Logging 框架的界面程式,以外观模式实现。可以在软件部署的时候决定要使用的 Logging 框架,目前主要支援的有Java Logging API、Log4j及logback等框架。以MIT 授权方式发布。其作者是 Log4j 以及 Logback 的作者 Ceki Gülcü

    其实,SLF4J只是一个门面服务而已,他并不是真正的日志框架,真正的日志的输出相关的实现还是要依赖其背后的日志实现Log4j2、logback等日志框架的。

    Commons-Logging

    Apache Commons Logging(原名 Jakarta Commons Logging,JCL)是一个基于Java的日志记录实用程序,是用于日志记录和其他工具包的编程模型。它通过其他一些工具提供API,日志实现和包装器实现。

    commons-logging和SLF4J的功能是类似的,主要是用来做日志 门面的。提供更加好友的API工具。

    四、日志桥接

    这里我们用Slf4j为例,通过Slf4j可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在它编译时需要静态绑定真正的Log库。使用Slf4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。

    这个东西要用图才能说得清楚,借用官网一张图:

    在这里插入图片描述

    包名桥接流功能
    jcl-over-slf4j.jarjcl -> slf4jJakarta Commons Logging日志框架到 slf4j 的桥接
    jul-to-slf4j.jarjuc -> slf4jjava.util.logging的日志桥接到 slf4j
    log4j-over-slf4j.jarlog4j -> slf4j将log4j 的日志,桥接到slf4j
    osgi-over-slf4j.jarosgi -> slf4j将osgi环境下的日志,桥接到slf4j
    slf4j-api.jarslf4j 的api接口jar包
    slf4j-jcl.jarlf4j -> jclslf4j 转接到 Jakarta Commons Logging日志输出框架
    slf4j-jdk14.jarslf4j -> julslf4j 转接到 java.util.logging,注意这个包不能和jul-to-slf4j.jar同时用,否则会死循环!
    slf4j-log4j12.jarslf4j -> log4jslf4j 转接到 log4j,注意这个包不能和log4j-over-slf4j.jar同时用,否则会死循环!
    slf4j-nop.jarslf4j -> nullslf4j的空接口输出绑定,丢弃所有日志输出
    slf4j-simple.jarslf4j -> slf4j-simpleslf4j自带的简单日志输出接口

    其实,在现在的日志框架中,有些框架本身也有针对其他的日志框架做一部分桥接的功能,如Log4j2

    包名桥接流功能
    log4j-1.2-api.jarlog4j -> log4j2将log4j 的日志转接到log4j2日志框架,注意这里的1.2不是版本号,而是1-to-2的意思
    log4j-api.jarlog4j2的api接口jar包
    log4j-core.jarlog4j2的日志输出核心jar包
    log4j-slf4j-impl.jarslf4j -> log4j2slf4j 转接到 log4j2 的日志输出框架
    log4j-to-slf4j.jarlog4j2 -> slf4j将 log4j2的日志桥接到 slf4j
    log4j-juljul -> log4j2将jul的日志桥接到log4j2

    从这里就已经可以看到,日志框架之间的关系有点乱。

    因为log4j2和slf4j都能对接多种日志框架,所以这些包的依赖,作用,还有命名,都容易让人混淆。

    PS:Log4j第一代的包名就叫Log4j,其最新的版本为2012年更新的1.2.17,后续的各种log4j-xxx,其实大部分都属于Log4j2的包了

    下面我们可以演示下各种日志类型的桥接包应该如何引入

    log4j -> log4j2

    那么就得去掉 log4j 1.x jar,添加log4j-1.2-api.jar,配合 log4j-api-2.x.x.jar 和 log4j-core-2.x.x.jar 即可,依赖如下

    log4j-1.2-api.jar
        log4j-api-2.x.x.jar
            log4j-core-2.x.x.jar
    

    log4j2 -> log4j

    这里我们只是演示如何做桥接,实际上当然不建议这么做的。
    理清了上面的jar包作用,就会发现,可以通过 log4j2 -> slf4j -> log4j 的方式来实现。

    需要的jar包,根据依赖关系分别是:

    log4j-api-2.x.x.jar
        log4j-to-slf4j.jar
            slf4j-api-x.x.x.jar
                slf4j-log4j12-x.x.x.jar
                    log4j-1.2.17.jar
    

    log4j -> slf4j

    将代码中的log4j日志桥接到 slf4j,需要如下jar包

    log4j-over-slf4j-x.x.x.jar
        slf4j-api-x.x.x.jar
    

    log4j2 -> slf4j

    将代码中的log4j2日志桥接到 slf4j,需要如下jar包

    log4j-api-2.x.x.jar
        log4j-to-slf4j-2.x.x.jar
            slf4j-api-x.x.x.jar
    

    slf4j -> log4j2

    将slf4j日志,采用log4j2实现进行输出,需要如下jar包

    slf4j-api-x.x.x.jar
        log4j-slf4j-impl.jar
            log4j-api.jar
                log4j-core.jar
    

    五、Spring日志解析

    spring日志依赖

    通常在我们的spring-boot-starter依赖中,会默认引入日志依赖如下:

    在这里插入图片描述

    我们通过查看Spring默认的日志依赖引入,可以清楚的看到,其使用日志门面slf4j来适配底层的日志框架,而日志框架用的则是logback,同时提供了对Java默认的JUL转换的SLF4J的适配器。

    细心的朋友们可以看到,这里spring还默认引入了一个log4j-to-slf4j的适配器,在我们主动将该配置Exclude之后其并不会影响我们项目的运行。

    PS:这里的log4j-to-slf4j大家不要以为是Log4j一代哈,根据上文日志桥接章节所说,它其实是Log4j2,只是官方省写了2,其作用是将 log4j2的日志桥接到 slf4j

    在这里插入图片描述

    那么为什么Spring默认要引入这个配置呢?

    这其实是为了提高我们代码依赖的鲁棒性,现如今,很多的组件/框架都会使用日志进行日志打印,而我们无法保证他们用的一定是logback/log4j2,因此,spring通过默认引入log4j2的桥接包,可以在我们引入使用log4j2作为日志框架的第三方组件时,自动将其桥接到slf4j,进而使用我们指定的日志框架(如spring默认的logback)实现进行打印

    为什么Spring默认使用Logback而不是Log4j2作为日志实现?

    针对这个问题,大家可以查看该链接进行了解

    修改日志实现

    如果我们不想使用Spring默认的日志框架,那么也可以采用类似的方式将它们对应的 spring-boot-starter 依赖模块加到 Maven 依赖中即可,如Log4j2使用如下依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    

    但一定不要将这些完成同一目的的 spring-boot-starter 都加到依赖中(这就是我们开头讲到的为什么有些日志依赖需要我们主动排除掉)

    根据不同的日志系统,可以按如下规则组织配置文件名,就能被Spring正确加载:

    • Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
    • Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
    • Log4j2:log4j2-spring.xml, log4j2.xml
    • JDK (Java Util Logging):logging.properties

    Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件,spring boot可以为它添加一些spring boot特有的配置项

    如果你即想完全掌控日志配置,但又不想用logback.xml作为Logback配置的名字,可以通过logging.config属性指定自定义的名字:

    logging.config=classpath:logging-config.xml
    

    总结

    在Java生态体系中,围绕着日志,有很多成熟的解决方案。关于日志输出,主要有两类工具。

    一类是日志框架,主要用来进行日志的输出的,比如输出到哪个文件,日志格式如何等。 另外一类是日志门面,主要一套通用的API,用来屏蔽各个日志框架之间的差异的。

    所以,对于Java工程师来说,关于日志工具的使用,最佳实践就是在应用中使用如Log4j2/Logback + SLF4J 这样的组合来进行日志输出。

    这样做的最大好处,就是业务层的开发不需要关心底层日志框架的实现及细节,在编码的时候也不需要考虑日后更换框架所带来的成本。这也是门面模式所带来的好处。

    综上,请不要在你的Java代码中出现任何Log4j等日志框架的API的使用,而是应该直接使用SLF4J这种日志门面。

    文章参考链接:
    https://www.jianshu.com/p/85d141365d39
    https://www.hollischuang.com/archives/3000
    https://www.jianshu.com/p/d7b0e981868d
    https://www.springboottutorial.com/logging-with-spring-boot-logback-slf4j-and-log4j

    展开全文
  • Java日志框架性能比较

    千次阅读 2019-01-18 16:26:44
    Java日志框架性能比较 1 Java日志框架性能比较 前面几章,笔者分别介绍了log4j,logback,log4j2三大日志实现框架。 接下来,就用具体的数据比较下,哪个日志框架的性能更好! 单线程:外循环100次,内循环100000次; ...

    Java日志框架性能比较

    1 Java日志框架性能比较

    前面几章,笔者分别介绍了log4j,logback,log4j2三大日志实现框架。

    接下来,就用具体的数据比较下,哪个日志框架的性能更好!

    单线程:外循环100次,内循环100000次;

    多线程:开启100个线程,每个线程执行100000次;

    1.1 测试代码:

    (1)log4j:

    public class log4jDemo {
    
        Logger logger = Logger.getLogger(log4jDemo.class);
    
        @Test
        public void testThread() throws InterruptedException {
            int THREAD_NUM = 100;
            final int LOOP_NUM = 100000;
    
            final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
            long start = System.currentTimeMillis();
            for(int x= 0;x < THREAD_NUM;x++){
                new Thread(new Runnable() {
                    public void run() {
                        for (int y = 0; y < LOOP_NUM; y++) {
                            logger.info("Info Message!");
                        }
                        countDownLatch.countDown();
                    }
                }).start();
            }
            countDownLatch.await();
            System.out.println(System.currentTimeMillis() - start);
        }
    
        @Test
        public void test() throws InterruptedException {
            int X_NUM = 100;
            int Y_NUM = 100000;
    
            long start = System.currentTimeMillis();
            for(int x=0;x < X_NUM;x++) {
                for (int y = 0; y < Y_NUM; y++) {
                    logger.info("Info Message!");
                }
            }
            System.out.print(System.currentTimeMillis() - start);
        }
    }
    

    (2)logback:

    public class logbackDemo {
    
        Logger logger =  LoggerFactory.getLogger(logbackDemo.class);
    
        @Test
        public void testThread() throws InterruptedException {
            int THREAD_NUM = 100;
            final int LOOP_NUM = 100000;
    
            final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
            long start = System.currentTimeMillis();
            for(int x= 0;x < THREAD_NUM;x++){
                new Thread(new Runnable() {
                    public void run() {
                        for (int y = 0; y < LOOP_NUM; y++) {
                            logger.info("Info Message!");
                        }
                        countDownLatch.countDown();
                    }
                }).start();
            }
            countDownLatch.await();
            System.out.println(System.currentTimeMillis() - start);
        }
    
        @Test
        public void test() {
            int X_NUM = 100;
            int Y_NUM = 100000;
    
            long start = System.currentTimeMillis();
            for(int x=0;x<X_NUM;x++) {
                for (int y = 0; y < Y_NUM; y++) {
                    logger.info("Info Message!");
                }
            }
            System.out.print(System.currentTimeMillis()-start);
        }
    }
    

    (3)log4j2:

    public class log4j2Demo {
        private Logger logger = LogManager.getLogger(log4j2Demo.class);
    
        @Test
        public void testThread() throws InterruptedException {
            int THREAD_NUM = 100;
            final int LOOP_NUM = 100000;
    
            final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
            long start = System.currentTimeMillis();
            for(int x= 0;x < THREAD_NUM;x++){
                new Thread(new Runnable() {
                    public void run() {
                        for (int y = 0; y < LOOP_NUM; y++) {
                            logger.info("Info Message!");
                        }
                        countDownLatch.countDown();
                    }
                }).start();
            }
            countDownLatch.await();
            System.out.println(System.currentTimeMillis() - start);
        }
        
        @Test
        public void test() throws InterruptedException {
            int X_NUM = 100;
            int Y_NUM = 100000;
    
            long start = System.currentTimeMillis();
            for(int x=0;x<X_NUM;x++) {
                for (int y = 0; y < Y_NUM; y++) {
                    logger.info("Info Message!");
                }
            }
            System.out.print(System.currentTimeMillis() - start);
        }
    }
    

    1.2 配置文件:

    (1)log4j:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration>
    
        <!--无缓存,立即输出-->
        <appender name="FILE" class="org.apache.log4j.FileAppender">
            <param name="File" value="e:/log.out" />
            <param name="append" value="true"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %p %c - %m%n" />
            </layout>
        </appender>
    
        <!--有缓存,不立即输出-->
        <appender name="FILE" class="org.apache.log4j.FileAppender">
            <param name="File" value="e:/log.out" />
            <param name="append" value="true"/>
            <param name="immediateFlush" value="false"/>
            <param name="bufferedIO" value="true"/>
            <param name="bufferSize" value="8192"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %p %c - %m%n" />
            </layout>
        </appender>
    
        <!--异步appender-->
        <appender name="AsyncAppender" class="org.apache.log4j.AsyncAppender">
            <appender-ref ref="FILE"/>
        </appender>
    
        <root>
            <priority value="info" />
            <appender-ref ref="FILE" />
            <appender-ref ref="AsyncAppender" />
        </root>
    </log4j:configuration>
    

    (2)logback:

    <configuration >
    
        <!--无缓存,立即输出-->
        <appender name="FILE" class="ch.qos.logback.core.FileAppender">
            <file>e:/log.out</file>
            <append>true</append>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} %p %c - %m%n</pattern>
            </encoder>
        </appender>
    
        <!--有缓存,不立即输出-->
        <appender name="FILE" class="ch.qos.logback.core.FileAppender">
            <file>e:/log.out</file>
            <append>true</append>
            <immediateFlush>false</immediateFlush>
            <bufferSize>8192</bufferSize>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} %p %c - %m%n</pattern>
            </encoder>
        </appender>
    
        <!--异步appender-->
        <appender name ="ASYNC" class= "ch.qos.logback.classic.AsyncAppender">  
            <discardingThreshold>0</discardingThreshold>  
            <queueSize>128</queueSize>  
            <appender-ref ref ="FILE"/>  
        </appender>  
        
        <root level="info">
            <appender-ref ref="ASYNC" />
            <appender-ref ref="FILE" />
        </root>
    </configuration>
    

    (3)log4j2:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="info" monitorInterval="30">
        <Appenders>
    
            <!--无缓存,立即输出-->
           <File name="File" fileName="e:/log.out" append="true">
                <<PatternLayout>
                    <Pattern>%d{HH:mm:ss.SSS} %p %c - %m%n</Pattern>
                </PatternLayout>
            </File>
    
            <!--有缓存,不立即输出-->
            <File name="File" fileName="e:/log.out" append="true"
                  immediateFlush="false" bufferedIO="true" bufferSize="8192">
                <PatternLayout>
                    <Pattern>%d{HH:mm:ss.SSS} %p %c - %m%n</Pattern>
                </PatternLayout>
            </File>
    
           <!--异步appender-->
            <Async name="Async">
                <AppenderRef ref="File"/>
            </Async>
        </Appenders>
        <Loggers>
            <Root level="info" >
                <AppenderRef ref="Async"/>
                <AppenderRef ref="File"/>
            </Root>
            <!--异步logger-->
            <AsyncRoot level="info" >
                <AppenderRef ref="File"/>
            </AsyncRoot>
        </Loggers>
    </Configuration>
    

    1.3 结果比较(毫秒)

    笔者从单线程、多线程2种情况下进行的测试!

    无论是多线程还是单线程,在启用缓存的情况下,系统性能得到了巨大的提升;

    在单线程情况下,相比较来说,启用异步Appender并没有对性能有较大的提升!

    值得一提的是,在log4j2中,多线程情况下,相对于同步logger来说,异步logger并没有进一步提高系统的性能,两者不相上下;

    但是,对于其他情况而言,异步logger还是有较大的提升!

    • 单线程

      (1)单线程,未开启缓存,立即刷出
        
            log4j:29772、29959、30911
            
            logback:25423、24552、26006
            
            log4j2:37927、38240、40164
        
        (2)单线程,开启缓存,不立即刷出
        
            log4j:9858、9677、9665
            
            logback:5561、5604、5611
            
            log4j2:5782、5505、5499
        
        (3)单线程,异步appender,未开启缓存,立即输出
        
            log4j:29683、29929、29385
            
            logback:33102、31779、30516
            
            log4j2:39298、39562、41872
        
        (4)单线程,异步appender,开启缓存,不立即输出
        
            log4j:10110、10068、10177
            
            logback:8753、9112、8922
            
            log4j2:8692、8400、8252
      

      多线程

      (1)多线程,未开启缓存,立即刷出
      
            log4j:38541、37791、38366
        
            logback:35644、35463、35442
            
            log4j2:38544、38746、38706
        
        (2)多线程,开启缓存,不立即刷出
      
            log4j:13296、12938、12686
            
            logback:6547、6294、6576
            
            log4j2:5596、5423、5421
        
        (3)多线程,异步appender,未开启缓存,立即输出
      
            log4j:30844、32088、30734
            
            logback:44203、42191、43228
            
            log4j2:46804、46034、46232
        
        (4)多线程,异步appender,开启缓存,不立即输出
      
            log4j:10422、10204、10495
            
            logback:40249、40437、40173
            
            log4j2:7832、8447、8660
      
        (5)多线程,异步logger,未开启缓存,立即输出
      
            log4j2:40555、40245、40325
        
        
        (6)多线程,异步logger,开启缓存,不立即刷出
      
            log4j2:5319、5407、5305
      

    展开全文
  • Java日志框架对比

    2020-03-19 21:14:51
    日志框架基本介绍 日志框架主要为我们提供了将日志信息写入到文件/控制台/数据库或其他服务端的框架,好的日志框架应该能够提供良好的性能,能够为不同名称的日志提供不同的日志处理机制和日志等级,以及提供对某些...

    日志框架基本介绍

    日志框架主要为我们提供了将日志信息写入到文件/控制台/数据库或其他服务端的框架,好的日志框架应该能够提供良好的性能,能够为不同名称的日志提供不同的日志处理机制和日志等级,以及提供对某些特殊日志的过滤功能等等。
    常用的日志框架主要有SLF4j, Log4j, Log4j2, Logback, jdk logging, common logging等等。

    SLF4J

    1.提供了对其他日志框架的门面,提供了一个抽象的日志类,不同的日志系统通过对抽象日志类的实现,去调用自己的日志系统。具体可见如下(SLF4J官网提供的框架图)
    在这里插入图片描述
    通过上图我们知道,SLF4J只是提供了一个简单的门面,通过这个门面我们可以调用其他的日志系统去对我们的日志进行操作。

    2.桥接包

    包名称描述
    slf4j-jdk14slf4j到jdk-logging的桥梁
    slf4j-log4j12slf4j到log4j的桥梁,这里主要指1.2及以下版本
    log4j-slf4j-implslf4j到log4j2的桥梁,这里主要指2.0以上版本
    logback-classicslf4jlogback的桥梁
    slf4j-jclslf4j到commons-logging的桥梁

    3.其他日志系统与SLF4J集成

    1. Log4J
       <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.21</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.21</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
        </dependency>
    

    2)Logback
    由于logback-classic中集成了slf4j,所以不再需要额外引入slf4j.jar,当引入logback-classic时,会自动导入logback-core-1.2.3.jar和slf4j-api-1.7.25.jar。

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
        <scope>test</scope>
    </dependency>
    

    3)Log4j2

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.13.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.13.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.1</version>
    </dependency>
    

    Log4J

    log4j是之前用的比较广泛的日志系统,后来已经被logback和log4j2给替代了,引入了基本的概念,如日志等级的层级和Logger的层级,这些基本概念被现在的很多日志系统如log4j2,logback所使用.
    相关的jar包主要有log4j包,用于日志的处理。

    <dependency>
        <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>1.2.17</version>
    </dependency>
    

    具体介绍可查看log4j 1.2详解

    Logback

    Logback也是由开发log4j的同一个开发者所开发,主要为了提供log4j的性能,已经内部增加了对slf4j本地支持,同时增加了对filter的改善已经对配置文件的自动加载。
    主要包括3个核心组件
    1)logback-core:核心包
    2)logback-classic:实现了slf4j本地支持
    3)logback-access:与servlet容器进行集成,通过该包可以往HTTP-access

    Log4j2

    Log4j2是这三个框架中最新的框架,对log4j和logback框架都进行了改进,同时log4j2也提供了对slf4j的支持,以及对配置文件的自动重加载,同时提供了对lamba表达式的支持,以及为了提供异步写入机制等等。
    具体可参见log4j 2用法大全

    Common Logging

    Common Logging跟slf4j一样,也是为日志接口提供了一个门面,可以根据需要简单的切换日志系统,而不需要改动代码。该日志系统本身不提供日志接口的实现,需要跟log4j, JDK logging 一起搭配使用。
    另外由于Common Logging使用自己的ClassLoader动态的查找相关日志接口的实现类并加载,所以不能支持OSGI的不同实现使用自己的类加载器,从而导致common Logging基本比较少使用,日志门面基本都使用slf4j。

    JDK Logging

    JDK自带的日志系统,能配置日志系统的等级,可将日志写入控制台或文件,但是性能以及日志输出地等都相对比较差以及齐全,所以基本都比较少使用。

    展开全文
  • java日志框架选择与使用 一、我们常常听说的就是如下的日子框架,还不知道这么选?下面我来教大家怎么选 ①:JUL(java.util.logging) , ②:JCL(Jakarta Commons-Logging) 由apache公司Jakarta 小组开发的, ③:JBoss-...

    java日志框架选择与使用

    一、我们常常听说的就是如下的日子框架,还不知道这么选?下面我来教大家怎么选
    ①:JUL(java.util.logging) ,
    ②:JCL(Jakarta Commons-Logging) 由apache公司Jakarta 小组开发的,
    ③:JBoss-logging
    ④:logback
    ⑤:log4j
    ⑥:log4j2
    ⑦:slf4j(Simple Logging Facade for Java.)

    在这里插入图片描述
    我们Spring底层选择的是我们的这个JCL做为日志门面的
    SpringBoot 选择的是 SLF4J做为我们的日志门面(当时log4j,和logback)他选择了logback
    下图就是我们选择日志时的搭配方式
    在这里插入图片描述
    二、源码分析
    Spring4.Xspring底层使用的日志技术
    在这里插入图片描述
    我们从这里可以看出来,spring4.x获取的日志对象中,LOGGer对象是jCL的,而他底层搭配的技术点就是
    先去找log4j的日志实现,若没有找到底层去找jdk的日志框架.压根不支持logback,log4j2的日志技术.

    Spring5.x 底层使用的日志技术
    在这里插入图片描述
    三、结束,仔细研究本博客,相信日志对于你来说,会变的很简单。

    展开全文
  • 记得前几年工作的时候,公司使用的日志框架还是log4j,大约从16年中到现在,不管是我参与的别人已经搭建好的项目还是我自己主导的项目,日志框架基本都换成了logback,总结一下,logback大约有以下的一些优点:内核...
  • 最全Java日志框架详解

    千次阅读 2018-09-21 18:23:51
    最全Java日志框架详解  在项目开发过程中,我们可以通过 debug 查找问题。而在线上环境我们查找问题只能通过打印日志的方式查找问题。因此对于一个项目而言,日志记录是一个非常重要的问题。因 此,如何选择一个...
  • java日志框架详解总结(含配置)

    千次阅读 2018-05-25 10:17:41
    该篇是集合了百度众多的日志框架详解,java日志框架分析的总结篇。 具体网址: https://blog.csdn.net/foreverling/article/details/51385128 https://blog.csdn.net/chszs/article/details/8653460 ...
  • logback (Java 日志框架)简介Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-...
  • 日志门面简介常用门面框架常用日志实现日志门面和日志实现的关系日志框架出现时间顺序推荐使用 简介 门面模式(Facade Pattern),也称之为外观模式,其核心为:外部与一个子系统的通信必须通过一个统一的外观对象...
  • JUL全称Java util logging,是java原生的日志框架,使用时不需要另外引入第三方类库,相对于其他框架使用方便,学习简单,能够在小型的应用中灵活使用。 架构: Application:我们的程序应用。 LogManager:管理...
  • Java日志框架Logback配置总结 1、 常见的日志框架 j.u.l、Log4j 、Logback、Log4j2等等。 2、 logback日志级别 等级从低到高分别是:TRACE < DEBUG < INFO < WARN < ERROR 1.如果logger没有被分配级别,...
  • java日志框架避免冲突的终极思路

    千次阅读 2018-04-26 14:52:26
    原文地址:...log4j-over-slf4j和slf4j-log4j12是跟java日志系统相关的两个jar包,当它们同时出现在classpath下时,就可能会引起堆栈溢出异常。异常信息大致如下(摘自slf4j官网文档Detect...
  • Java程序员最常用的8个Java日志框架

    千次阅读 2016-12-26 16:52:48
    来源...然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日志可以帮助我们更好更快地定位bug;在运行维护阶段,日志系统又可以帮我们记录大部分的异常信息,从而帮助我们更好
  • Java 日志框架

    2018-05-31 22:34:21
    摘要: 在Java中工程中,输出日志需要使用一个或者多个日志框架,这些框架提供了必要的对象、方法和配置来传输消息。 java.util.logging 在JDK 1.4 版本之后,提供了日志的API ,可以通过简单的配置处理日志。 ...
  • JAVA日志框架

    千次阅读 2016-09-13 10:02:05
    1、日志框架 提供日志调用的接口,实际的日志输出委托给日志系统实现。 JCL(Jakarta Commons Logging):比较流行的日志框架,很多框架都依赖JCL,例如Spring等。 SLF4j:提供新的API,初衷是配合Logback使用...
  • Java 日志框架解析:设计模式、性能

    千次阅读 2017-09-28 10:00:54
    在平常的系统开发中,...一个好的日志框架,既要方便易用,也要有较好的性能,减少日志输出对系统内存、CPU 的影响。 研究一款开源项目,学到的不仅仅是这个项目本身,还会学到很多设计思想,可以利用到日常工作中。
  • 用于软件架构项目的 Java 日志框架,作者为 Nicolas ANDRE 先生。 文档 链接到我们项目的 JavaDoc: 安装说明 下载文件 将它添加到您的 java 项目(例如在“lib”文件夹中) 然后将其添加到您项目的 BuildPath 中 ...
  • java日志框架原理(一)

    千次阅读 2018-10-11 01:35:00
    日志代理框架 常用的一些日志工具 一般打日志,有许多种选择,像slf4j, log4j, logback, jul(java.util.logging.Logger), SimpleLog(System.err), commons-logging等。这些大致可以分为两类,代理类和工具类,其中...
  • Java 日志框架详解

    2020-11-05 19:14:54
    java.util.logging:是 JDK 在 1.4 版本中引入的 Java 原生日志框架 Log4j:Apache 的一个开源项目,可以控制日志信息输送的目的地是控制台、文件、GUI 组件等,可以控制每一条日志的输出格式,这些可以通过一个...
  • 日志那些事之一—java日志框架分类

    千次阅读 2018-03-06 19:56:19
    本系列日志文章主要是针对项目上遇到的日志问题,发散下思维,比较广的介绍下java中常见以及常用的日志框架,并通过实例代码演示。系列文章主要分为三大部分: 了解日志的作用,了解java中常用的日志框架; ...
  • JAVA日志框架适配-冲突解决方案.docx

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 247,685
精华内容 99,074
关键字:

java的日志框架

java 订阅