在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的实例:
有时间继续更新