日志是应用程序运行中不可缺少的一部分,JAVA中有很多已经成熟的方案,尽管记录日志是应用开发中并不可少的功能,在 JDK 的最初版本中并不包含日志记录相关的 API 和实现。相关的 API(java.util.logging 包,JUL)和实现,直到 JDK 1.4 才被加入。因此在日志记录这一个领域,社区贡献了很多开源的实现。其中比较流行的包括 log4j 及其后继者 logback。除了真正的日志记录实现之外,还有一类与日志记录相关的封装 API,如 Apache Commons Logging 和 SLF4J。这类库的作用是在日志记录实现的基础上提供一个封装的 API 层次,对日志记录 API 的使用者提供一个统一的接口,使得可以自由切换不同的日志记录实现。比如从 JDK 的默认日志记录实现 JUL 切换到 log4j。这类封装 API 库在框架的实现中比较常用,因为需要考虑到框架使用者的不同需求。在实际的项目开发中则使用得比较少,因为很少有项目会在开发中切换不同的日志记录实现。
日志的实现
JAVA 中都有 java.util.logging, log4j ,logback,log4j2 等日志实现。其中logback是log4j作者觉得log4j已经太烂不想再改了,重新写的一个实现。Log4j本来一统江湖好好的,后来被人说方法上太多同步修饰符,在高并发下性能太烂。Netflix的blitz4j就重新实现了一次log4j项目,去掉了大量的同步修饰符,不过其负责人自己说,新项目还是建议直接用logback。不过,后来apache社区感觉slf4j和logback都是log4j作者开的qos.ch公司的产品,日志是件很重要的事情,不应该操控在一家公司手里。所以又以纯社区驱动搞了log4j2,参考了logback,也做了一些自己的改动。
SLF4J
http://www.slf4j.org/manual.html
SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只为各种日志实现提供一个简单统一的接口,从而使得最终用户能够在部署的时候配置自己希
望的实现。slf4j只是一个日志外壳,需要你加入slf4j-jdk14.jar, slf4j-log4j12.jar或logback.jar,将日志调用转发到实际的日志框架。在classpath中有哪个jar包,slf4j就会选择哪个实现。如果错误的同时存在多个jar包。比如:选择JDK自带的日志系统,则只需要将slf4j-api-xxx.jar和slf4j- jdk14-xxx.jar放置到classpath中即可,如果中途无法忍受JDK自带的日志系统了,想换成log4j的日
志系统,仅需要用slf4j-log4j12-xxx.jar替换slf4j-jdk14-xxx.jar即可(当然也需要log4j的jar及配置文件)。
替换默认的common-logging
有些第三方的工具包,已经直接使用了log4j, common-logging 或 java.util.logging。如果我们最后决定使用log4j做最终输出,则需要放一个jcl-over-slf4j.jar和 jul-to-slf4j.jar来替换common-logging或java.util.logging的api,将日志请求转发给 slf4j,slf4j再转发给log4j,此时还需要保证,classpath里没有common-logging.jar。 而原本直接使用log4j的就不需要做任何改动。
Maven中使用SLF4J替换Common-logging(比如默认的Spring就依赖Common-logging)
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency>
<!--slf4j--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!--spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency>
绑定关系对应表
As mentioned previously, SLF4J supports various logging frameworks. The SLF4J distribution ships with several jar files referred to as "SLF4J bindings", with each binding corresponding to a supported framework.
- slf4j-log4j12-1.7.9.jar
- Binding for log4j version 1.2, a widely used logging framework. You also need to place log4j.jar on your class path.
- slf4j-jdk14-1.7.9.jar
- Binding for java.util.logging, also referred to as JDK 1.4 logging
- slf4j-nop-1.7.9.jar
- Binding for NOP, silently discarding all logging.
- slf4j-simple-1.7.9.jar
- Binding for Simple implementation, which outputs all events to System.err. Only messages of level INFO and higher are printed. This binding may be useful in the context of small applications.
- slf4j-jcl-1.7.9.jar
- Binding for Jakarta Commons Logging. This binding will delegate all SLF4J logging to JCL.
- logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)
- Native implementation There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements SLF4J natively. Logback's
ch.qos.logback.classic.Loggerclass is a direct implementation of SLF4J'sorg.slf4j.Loggerinterface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.
log4j
http://logging.apache.org/log4j/1.2/
log4j与slf4j是最常见的一种方式
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.10</version> </dependency>
log4j.properties
#Log4j log4j.rootLogger=info,console # 控制台日志设置 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout #log4j.appender.console.layout.ConversionPattern=%p %d{HH:mm:ss.SSS} [%X{ip}] - %l %m%n log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n # 文件日志设置 log4j.appender.file=org.apache.log4j.DailyRollingFileAppender #log4j.appender.file.file=/opt/logs/test.log log4j.appender.file.DatePattern='.'yyyy-MM-dd log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n
web.xml
<context-param> <param-name>webAppRootKey</param-name> <param-value>Log4j</param-value> </context-param> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.properties</param-value> </context-param> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>10000</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener>
JUnit
运行单元测试时,报以下错误
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
原因是找不到默认的log4j配置文件,可手动指定,如:
Log4jConfigurer.initLogging("classpath:log4j.test.properties");
log4j.test.properties是为执行单元测试类使用的一个配置文件
log4j2
http://logging.apache.org/log4j/2.x/ log4j2 是log4j的升级版
logback
http://logback.qos.ch/ logback是对slf4j的原生实现
Logstash
Refer:
Java 日志管理最佳实践
http://www.ibm.com/developerworks/cn/java/j-lo-practicelog/
为什么要使用SLF4J而不是Log4J
http://www.importnew.com/7450.html