【日志】基本概念
1.日志工具介绍
有很多的日志工具,主要分为两类:
- 日志实现类:Log4j、Logback、java自带 java.util.logging.Logger、Log4j2。
(1)Log4j:日志级别从低到高依次是:“调试( DEBUG )”“信息( INFO )”“警告( WARN )”“错误(ERROR )”“致命错误( FATAL )”。
(2)Logback - 日志门面:SLF4J ,common-logging。
2.具体如何应用。
早期传统的项目一般直接使用日志实现类Log4j和Logback。现在推荐使用日志门面模式。门面模式能解决什么问题呢?
- 从设计模式的角度考虑,它是用来在log和代码层之间起到门面的作用。
因为只使用slf4j提供的接口
,即可隐藏日志的具体实现
。可以实时的根据情况来调换具体的日志实现类
。日志和代码之间进行解耦
。因此可以在应用中灵活切换日志系统。 - 最终日志的格式、记录级别、输出方式等通过具体
日志系统
的配置来实现。 - 一个应用程序用到了多个组件,如果组件紧紧依赖日志实现类并且是不同的,那么应用程序就会有多份日志输出了。组件开发者着非常不希望这样。
3.common-logging(Apache )
(1)为了统一各种各样的日志工具而出现的
,它仅仅对Log4j(当然还包括其它LOG实现)作了一层包装
,common-logging会通过动态查找的机制,在程序运行时自动发现当前应用依赖的日志框架实现,按照用户配置或者默认顺序决定应该使用的日志框架。
用户没有进行配置,默认顺序
是:如果能找到Log4j 则默认使用log4j 实现,如果没有则使用JDK14Logger 实现,再没有则使用commons-logging 内部提供的SimpleLog 实现
(2)LogFactory 是对外的接口,使用方式为:LogFactory.getLog(Test.class)。
protected final Log logger = LogFactory.getLog(getClass());
(3)包装:common-logging中的impl 实现类中封装了已有的多种日志工具,比如 Log4JLogger 是对 log4j 的封装,Jdk14Logger 是对 java.util.logging.Logger 的封装, AvalonLogger/LogKietLogger 是另外日志工具的封装。最后 SimpleLog 是 common-logging 自己实现的 Logger,功能简单,`是其他工具不能使用时的最终方案。
Spring框架默认使用common-logging写日志。
4. SLF4J
和common-logging 功能和定位相似,由一个基础的包 slf4j-api 定义了统一的日志接口 Logger,工厂接口 LoggerFactory。
(1)在编译时静态绑定
真正的Log库。使用Slf4j时,如果你需要使用某一种日志实现,必须选择正确的Slf4j的jar包的集合
。
(2)SLF4J 的作者就是 Log4j和Logback 的作者 Ceki Gülcü,他宣称 SLF4J 比 Log4j 更有效率,而且比 Apache Commons Logging (JCL) 简单、稳定。
(3)软件部署的时候决定要使用的 Logging 框架,目前主要支援的有Java Logging API、Log4j及logback等框架。
SLF4J 结合Log4j,需要的jar包为slf4j-api.jar、slf4j-log4j12.jar、log4j.jar,其中绑定包slf4j-log4j12.jar指定了要使用的实现库
。
<!-- logger -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
5.日志兼容
J2EE项目中,经常会用到很多第三方的开源组件和软件,这些组件都使用各自的日志组件
,比较常用的包括slf4j,common-log, log4j等,很多老的开源软件(包括TOMCAT)使用的是JDK14-LOGGER。这些日志都有自己独立的配置。但是在项目实际部署的时候,需要把所有开源软件和项目程序的各种日志都整合到日志文件
中输出,包括tomcat。具体做法:
- 针对各自日志体系做了代理 ,输出到了sfl4j接口中。log4j对应log4j-over-slf4j,common-logging对应jcl-over-slf4j等。
- 桥接和被桥接的包不能同时出现,不然会出现死循环了,比如sfl4j既桥接了log4j又被log4j桥接,那log4j输出调用会指向slf4j,slf4j又指向log4j如此循环。一定要注意排除掉无用的包。log4j和log4j-over-slf4j依赖包不能同时出现。
(1)log4j、commons-log、slf4j、 java.util.logging四种日志同时都统一使用logback输出的案例:
<!--以下是slf4j使用logback,桥接其它日志。-->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<!--使用 logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.1</version>
</dependency>
<!--桥接common-logging-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.14</version>
</dependency>
<!--桥接log4j-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.7</version>
</dependency>
(2)log4j、commons-log、slf4j、 java.util.logging四种日志同时都统一使用log4j输出的案例:
<properties>
<slf4j.version>1.7.2</slf4j.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<!-- LOGGING begin -->
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- slf4j-log4j绑定 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- common-logging 实际调用slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- java.util.logging 实际调用slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- LOGGING end -->
整合说明:
(1)slf4j的日志会自动根据slf4j-log4j12-xxx.jar输出日志到log4j,无需配置。
(2)commons-log的日志会自动根据jcl-over-slf4j转到log4j输出,无需配置
(3)jdk14-logger的日志输出(如:tomcat,restlet等软件)可以根据jul-to-slf4j提供的Handler转移日志输出到slf4j,然后又slf4j转log4j输出。但是需要配置或编程方式设置 。配置步骤:
- 建立jdk14-logger的配置文件logger.properties.加入Hander配置:
- handlers = org.slf4j.bridge.SLF4JBridgeHandler
- 然后在启动程序或容器的时候加入JVM参数配置JDK日志只是用SLF4JBridgeHandler处理:
-Djava.util.logging.config.file=/path/logger.properties
6.总结
- common-logging本身提供的日志比较弱,一般都是结合Log4j一起使用。
- slf4j 与 common-logging比较:
(1)common-logging通过动态查找的机制,在程序运行时自动找出真正使用的日志库。不支持OSGI框架。
(2)在编译时静态绑定真正的Log库,因此可以再OSGI中使用。 - Log4j 与 LogBack 比较:LOGBack具有极佳的性能比,如判定是否记录一条日志语句的操作,其性能得到了显著的提高