java基础 - 白话讲懂java的log江湖

在java1.4之前sun并没有考虑到log这一块,所以在最开始的程序员只能使用System.out.println("")。这种又消耗性能又只能输出到控制台的方式记录log。很苦逼。

        System.out.println("Hello world");

有一位大神实在受不了了,就自己写了一个工具log4j。相对于System.out好处太多了,下面随便列了一些:线程安全,支持多输出源,支持日志级别,配置简单,输出格式可控,开源协议,速度快。这位大神就是(Seki)赛基.

赛基把log4j捐献给了Apache开源软件基金会。Apache试图说服sun公司将log4j加入到JDK中,但是sun一直没有同意。

        Logger log = Logger.getLogger(Log4JLogger.class);
        log.info("Hello world");

后来sun自己开发了一套log工具放在util包中,java.util.logging (JUL)用来对抗log4j。

        Logger logger= Logger.getLogger(JucLoger.class.getName());
        logger.info("hello world!");

于是开发界中对log的使用就比较混乱了,有的用log4j有的用java自带的JUL,他们之间的接口不一样,很容易混淆。

于是Apache开发了一套Jakarta Commons Logging(JCL),作为一个接口标准,使用JCL做为接口,下面使用JUL或者log4j作为实现都可以。也就是我们用到的commons-logging-xx.jar。JCL用起来很方便,他默认的配置:如果能找到Log4j 则默认使用log4j 实现,如果没有则使用jul(jdk自带的) 实现,再没有则使用jcl内部提供的SimpleLog 实现,所以JCL总能为你找到一个实现。

        Log logger = LogFactory.getLog(CommonLogger.class);
        logger.info("Hello Wrold!!");

但是JCL也存在一个问题,效率低,容易引发混乱,在使用了自定义ClassLoader的程序中使用JCL会引发内存泄露,

于是乎大神赛基又出手了,他又自己写了一套新的接口slf4j用来代替JCL,并自带一个实现logBack。这个接口的牛逼之处在于他为现在所有存在的log实现写了一个桥接器,不管你老系统里面用的是什么实现,现在使用slf4j都可以兼容,并且为其统一出口。

所以赛基有一次统一了log江湖。

后来apache重构了log4j,吸取了logback的一些优秀设计并推出了log4j2。现在apache已经不维护log4j了并推荐使用者使用log4j2.

现在主流都推荐使用log4j2和logback,

老牌的 Log4j2 凭借着入场早、背靠 Apache 两大优势有着不错的用户支持,官网文档也很完善。

新生的 Logback 凭借着 SLF4j 的原生实现以及被 Spring Boot 钦点的日志框架(Spring 也提供了Log4j2 的 starter,切换依赖即可完成更换日志框架,前文讲过,此处不再赘述),同样也拥有着很好的前景。

总的来说现在二者不想上下。

虽然有这么多的实现,但是对于log的设计都基本上是一样的,对于log的框架都包含三个部分:

输入,输出,格式

输入就是哪些信息需要被log记录下来。

输出就是把记录下来的这些log记录在哪里,文件控制台。

格式就是用输出这些log的格式是什么样的。


java.util.logging(JUC) 的使用实例:

JUC 是JDK自带的log机制,所以不用引入任何package,使用java自带的JUC,框架一样的都是控制三个组件,输入,输出,格式化:

输入: Logger 主类用来记录log
格式: Formatter 借口用来对日子进行格式化。
输出: ConsoleHandler/FileHandler 用来控制将log输出到哪里。
import java.io.IOException;
import java.util.logging.*;

public class JucLoger {
    public static void main (String [] args ) throws InterruptedException, IOException {
        Logger logger= Logger.getLogger(JucLoger.class.getName());
        logger.setLevel(Level.INFO);

        Formatter fmatter = new MyLogFormater();

        ConsoleHandler console = new  ConsoleHandler();
        FileHandler file = new FileHandler("c:/log/test.log");

        file.setFormatter(fmatter);
        console.setFormatter(fmatter);

        logger.addHandler(console);
        logger.addHandler(file);

        logger.info("hello world!");
    }

控制台输出结果:

INFO| ---- |hello world!
九月 27, 2020 4:18:21 下午 JucLoger main
信息: hello world!

文件输出结果:

log4j的使用实例

第一步 引入log4j的jar包

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

第二步 在source目录下面加入配置文件:

#####配置根元素
log4j.rootLogger=INFO,console,file
#存储INFO以及以上级别的记录
#file的输入地址为文件
#console表示输出到控制台
log4j.appender.file=org.apache.log4j.RollingFileAppender
#以下是具体的目录
log4j.appender.file.File=d:/a/test.log
#每个文件的最大大小
log4j.appender.file.MaxFileSize=20KB
#最多可以是多少个文件
log4j.appender.file.MaxBackupIndex=3
#信息的布局格式-按指定的格式打出
log4j.appender.file.layout=org.apache.log4j.PatternLayout
#具体的布局格式 - %d为时间
#log4j.appender.file.layout.ConversionPattern=%d %p [%c] %m %l %n
log4j.appender.file.layout.ConversionPattern=%d %p [%l]\:%m -%t%n 

#以下配置输出到控制台的配置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#log4j.appender.console.layout.ConversionPattern=%d %p [%c] %m%n
log4j.appender.console.layout.ConversionPattern=%d %p [%l]\:%m -%t%n 

第三步 直接在java中使用了:

import org.apache.log4j.Logger;

public class Log4JLogger {
    public static void main (String [] args ){
        Logger log = Logger.getLogger(Log4JLogger.class);
        log.info("Hello world");

    }
}

输出结果:

2020-09-27 16:33:30,653 INFO [Log4JLogger.main(Log4JLogger.java:8)]:Hello world -main
 
Process finished with exit code 0

log4j + commons-logging 的使用实例:

加入common logging的jar包:

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

直接在java中使用CommonLogging:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CommonLogger {
    public static void main (String [] args ){
        Log logger = LogFactory.getLog(CommonLogger.class);
        logger.info("Hello Wrold!!");
    }
}

因为前面我们在项目里面已经配置了log4j,

执行结果:

2020-09-27 16:49:44,169 INFO [CommonLogger.main(CommonLogger.java:8)]:Hello Wrold!! -main
 
Process finished with exit code 0

从下面的执行结果可以看出,现在依然使用的log4j的配置已经实现,按照我们前面提到优先级:

如果能找到Log4j 则默认使用log4j 实现,如果没有则使用jul(jdk自带的) 实现,再没有则使用jcl内部提供的SimpleLog 实现,所以JCL总能为你找到一个实现。

CommonLogging + SimpleLog的实例:

在resource文件目录下面加入文件commons-logging.properties内容如下:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

并加入sinpleLog的配置文件simplelog.properties:

org.apache.commons.logging.simplelog.defaultlog=trace
org.apache.commons.logging.simplelog.log.level=debug
org.apache.commons.logging.simplelog.showlogname=true  
org.apache.commons.logging.simplelog.showShortLogname=true  
org.apache.commons.logging.simplelog.showdatetime=true  
org.apache.commons.logging.simplelog.dateTimeFormat=SimpleLogyyyy-MM-dd hh:mm:ss 

java运行:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CommonLogger {
    public static void main (String [] args ){
        Log logger = LogFactory.getLog(CommonLogger.class);
        logger.info("Hello Wrold!!");
    }
}

运行结果:

[INFO] Hello Wrold!!

Process finished with exit code 0

sl4j+logback的实例:

 

sl4j+log4j2的实例:

有时间继续更新

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值