java中,比较常见的日志框架有slf4j log4j logback 以及common-logging。
slf4j:全称为Simple Logging Facade for JAVA,java简单日志门面。是对不同日志框架提供的一个门面封装,实现了日志框架一些通用的api.而log4j logback是具体实现了的日志框架,slf4j提供了日志的统一接口,而不用去考虑日志的具体实现,也就是说,使用slf4j,你可以随意的切换log的实现,可以是log4j logback,或者是jdk中的sun logger。可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。
使用slf4j的常见代码:
Log logger = LogFactory.getLog(this.getClass());
slf4j静态绑定原理:slf4j会在编译时会绑定import org.slf4j.impl.StaticLoggerBinder; 该类里面实现对具体日志方案的绑定接入。任何一种基于slf4j 的实现都要有一个这个类。如:org.slf4j.slf4j-log4j12-1.5.6: 提供对 log4j 的一种适配实现。注意:如果有任意两个实现slf4j 的包同时出现,那么就可能出现问题。
log4j :是具体实现了的日志框架,是apache实现的一个开源日志组件,log4j不是对slf4j的原生实现,所以slf4j api在调用log4j时需要一个适配层
Logback:是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现slf4,使你可以很方便地更换成其它日志系统
common-logging:common-logging类似于slf4j,不过common-logging只是对log4j 和sun logger的封装,common-logging只是对log4j 和sun logger的统一接口,可以支持切换具体的日志实现,但只能在log4j 和sun logger中切换。是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱。所以使用common-logging,通常都是配合着log4j来使用。使用它的好处就是,代码依赖是common-logging而非log4j, 避免了和具体的日志方案直接耦合,在有必要时,可以更改日志实现的第三方库。
使用common-logging的常见代码:
Log logger = LogFactory.getLog(this.getClass())
动态查找原理:Log 是一个接口声明。LogFactory 的内部会去装载具体的日志系统,并获得实现该Log 接口的实现类。LogFactory 内部装载日志系统的流程
1寻找org.apache.commons.logging.LogFactory 属性配置。
2利用JDK1.3 开始提供的service 发现机制,会扫描classpah 下的META-INF/services/org.apache.commons.logging.LogFactory文件,若找到则装载里面的配置,使用里面的配置。
3从Classpath 里寻找commons-logging.properties ,找到则根据里面的配置加载。
4使用默认的配置:如果能找到Log4j 则默认使用log4j 实现,如果没有则使用JDK14Logger 实现,再没有则使用commons-logging 内部提供的SimpleLog 实现。
从上述加载流程来看,只要引入了log4j 并在classpath 配置了log4j.xml ,则commons-logging 就会使log4j 使用正常,而代码里不需要依赖任何log4j 的代码。
Log4j 与 LogBack 比较
在企业级开发中,大多使用logback来替换log4j,logback 重写了内部的实现,在某些特定的场景上面,比log4j效率要高很多。logback 是对于slf4j的原生实现。无论是选择log4j还是logback实现日志,在slf4j下,都不需要过多的配置,只需要在classpath路径下,存在相应的文件,就会自动加载对应的日志。
logback在spring mvc中的配置
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="false">
<property name="LOG_HOME" value="/data/wwwroot/log"/>
<property name="app.name" value="***"/>
<contextName></contextName>
<!-- console -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{100} - %msg%n</pattern>
</encoder>
</appender>
<!-- communication log -->
<appender name="communicationRolling" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME_COMMUNICATION}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME_COMMUNICATION}-%d{yyyy-MM-dd}.zip</fileNamePattern>
<maxHistory>30</maxHistory>
<!-- <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy> -->
</rollingPolicy>
<encoder><pattern>%d{HH:mm:ss} %-5level %logger{100} - %msg%n</pattern></encoder>
</appender>
<!-- error -->
<appender name="errorRolling" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${LOG_HOME_ERROR}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME_ERROR}-%d{yyyy-MM-dd}.zip</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder><pattern>%d{HH:mm:ss} %-5level %logger{100} - %msg%n</pattern></encoder>
</appender>
<logger name="com.communication" level="DEBUG">
<appender-ref ref="communicationRolling"/>
</logger>
<root level="ERROR">
<appender-ref ref="errorRolling" />
</root>
</configuration>
在spring boot中,可以使用springProfile来依据运行环境,控制不同的输出,但是在spring mvc中不支持
<!-- dev environment -->
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="console" />
</root>
</springProfile>
<!-- prod environment -->
<springProfile name="test,prod">
<root level="INFO">
<appender-ref ref="orderRolling" />
</root>
</springProfile>