前言
日志应该是除了代码之外,程序员最好的朋友了,它可以帮助我们定位问题、修复bug,或者是确认服务是否正常运转;很多时候我们做一次部署只是为了加几行日志;
而 Tomcat
作为经久畅销的web 服务器,一直是web 开发者首选,而 Tomcat
的原生日志是我们判断这个服务器是否正常运转的重要数据。
Java 日志组件
这里我们按照历史顺序简单介绍一下 Java
常用的日志组件,
JUL
(Java Util Logging): 是 jdk
自带的log 实现组件,虽然是官方出品但是它并没有被广泛使用,主要是下面几个原因
“1. JUL
出现的太晚了,2002年它才被放到 jdk1.4
中,当时已经有很多第三方的日志组件被广泛使用了
JUL
早期性能问题太明显,到JDK1.5
才有所改善,但是它和其他第三方日志组件logback
或log4j2
相比也还是有差距JUL
提供的功能不如第三方组件logback
或log4j2
完善
log4j
是在 logback
之前被广泛使用的日志实现组件,log4j
在设计上十分优秀,对后期的Java
日志框架有深远的影响,但是它在性能上存在缺陷;logback
出现之后就取代了 log4j
JCL
(Apache Commons Logging): apache 提出的 Log Facade
,只提供日志api,不提供实现,通过不同的 Adapter 来使用 JUL
或者 log4j
;在打印日志的时候调用的都是 JCL
指定的api ,具体实现是看当前的 classpath
中有什么实现,如果什么都没有
slf4j
(The Simple Logging Facade For Java): slf4j
是 Ceki Gülcü
开发的 Log Facade
,主要是因为Ceki Gülcü
觉得作为日志统一接口的 JCL
设计的不合理:
下面这种写法不管是否输出 debug
级别的时候都需要做一次字符串拼接,如果这种代码被反复调用就会产生很多无用的字符串拼接,影响性能。
1 | logger.debug("log:" + log); |
而官方给出的最佳时间方式是这样的:
1 | if (logger.isDebugEnabled()) { |
怎么看都是反人类的设计,所以在 slf4j
中,设计的api 是这样的1
logger.debug("log:{}", log);
logback
: logback
也是Ceki Gülcü
开发的日志实现,在 log4j
的基础上进行了改进,提供了更好的性能实现,异步logger,Filter 等更能多的特性。
Ceki Gülcü
给我们开发了很好用的日志组件,但是现在有了两个 Log Facade
和三个流行的 Log Implementation
,事情变的复杂了;Ceki Gülcü
作为一个完美主义者,为了我们能在不同的log 之间自由切换,他又开发了各种 Adapater
和 Bridge
来连接,这里盗用一张 slf4j
官网的图片
log4j2
: log4j2
的开发维护人员不想看着 log4j
被 slf4j/logback
所取代,在设计上很大程度的模仿了 slf4j/logback
,完全脱离log4j1.x
,在性能上实现了很大的提升,作为一个高仿品这里不多介绍。
Tomcat
的日志实现方法
Tomcat
内部整合的日志模块是 JULI
,JULI
是从 JCL
fork 过来的一个重命名分支,默认被硬编码使用 JUL
作为日志实现,从而保证 Tomcat
本身的日志和业务日志实现完美隔离。
而Tomcat
的日志的配置文件默认位置是 ${catalina.base}/conf/logging.properties
,如果无法读取或不存在的时候,就会去找${java.home}/lib/logging.properties
;在web应用的范围内也有一个日志配置文件 WEB-INF/classes/logging.properties
1 | # Licensed to the Apache Software Foundation (ASF) under one or more |