本教程使用 maven 来引入三方库,因此需要新建 maven 项目
JDK Logging 原生日志
相对于 System.out.println()
打印控制台信息,日志系统有输出格式,等级控制,日志持久化等优点,Java
标准库内置了日志包java.util.logging
,可以如下使用:
import java.util.logging.Logger;
public class Main {
public static void main(String[] args) {
Logger logger = Logger.getGlobal();
logger.info("log info");
logger.warning("log warning");
logger.fine("log fine");
logger.severe("log sever");
}
}
运行结果:
JDK
的 Logging
定义了7个日志级别,从高到第依次为 SERVER
、WARNING
、INFO
、CONFIG
、FINE
、FINER
、FINEST
,其中默认级别为 INFO
,因此 INFO
以下的级别是不会被打印的
Commons Logging 日志接口
使用原生 JDK
日志有些不便,因此可以使用 Commons Logging
作为接口来挂载 JDK
日志系统,默认情况下,Commons Loggin
自动搜索并使用 Log4j
,如果没有找到 Log4j
,再使用 JDK Logging
,下面来演示这两种配合:
Commons Logging + JDK Logging
引入依赖:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
测试类:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Main {
private static final Log log = LogFactory.getLog(Main.class);
public static void main(String[] args) {
log.info("log info");
log.warn("log warn");
log.debug("log debug");
}
}
Commons Logging 定义了6个日志等级,依次为 FATAL
、ERROR
、WARNING
、INFO
、DEBUG
、TRACE
,其中默认等级取决于其底层实现,即和 JDK Logging
相同,为 INFO
级别。
Commons Logging + Log4j
Log4j
是另一种日志系统,和 JDK Logging
等定位,它可以作为日志接口 Commons Logging
的另一种实现。
引入依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
在resource 目录下新建 Log4j
的配置文件 log4j.properties
#设置日志的级别,定义日志信息的输出目的
log4j.rootLogger=DEBUG, CA ,RFA
#定义CA的输出目的地为控制台
log4j.appender.CA=org.apache.log4j.ConsoleAppender
#布局为 PatternLayout 可以灵活地指定布局模式。
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
#设置输出格式
log4j.appender.CA.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%c]-[%p] %m%n
#定义R的输出目的地为文件,并且文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.RFA=org.apache.log4j.RollingFileAppender
#设置输出的文件地址
log4j.appender.RFA.File=D:\\temp\\Test_Log4j.log
#设置文件大小为100 kb 文件到达100时,产生一个新文件,
#MaxBackupIndex 最大记录的文件数为1 超过删除较早的。
log4j.appender.RFA.MaxFileSize=100KB log4j.appender.RFA.MaxBackupIndex=1
#以下和上面一样
log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
log4j.appender.RFA.layout.ConversionPattern=%p %t %c - %m%n
测试类:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Main {
private static final Log log = LogFactory.getLog(Main.class);
public static void main(String[] args) {
log.info("log info");
log.warn("log warn");
log.debug("log debug");
}
}
运行结果:
Log4j
默认日志级别也为 INFO
但在 log4j.properties
中我们将其配置为 DEBUG
,因此可以输出 log debug。
SLF4J + Logback 组合
除了上面的那些,日志还有一些常用的组合,如 SLF4J
+ Logback
其中 SLF4J
与 Commons Loggin
等定位,作为日志接口,而 Logback
则与 Log4j
等定位,作为日志实现。
引入依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
在resource 目录下新建 Logback
的配置文件 logback.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 从高到地低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志-->
<!-- 定义日志文件 输入位置 -->
<property name="logPath" value="D:/temp/logback/log-back.log"/>
<!-- 日志最大的历史 30天,这个参数要看你基于哪一种滚动策略【基于天,单位为天,月同理】本文件设置的多事基于天滚动策略 -->
<property name="maxHistory" value="30"/>
<!-- 日志输出格式【控制台】-->
<property name="logPatternConsoleLog"
value="%date{yyyy-MM-dd HH:mm:ss} | %highlight(%-5.5p) | %boldYellow(%-30.30c) | %boldGreen(%-8.8L): %magenta(%-10M) : %boldBlue(%-10.20t) | %cyan(%m) %n"/>
<!--提供两个格式的输出,如果觉得上面的信息太过详细,可使用下面的格式-->
<!-- <property name="logPatternConsoleLog"-->
<!-- value="%highlight(%-5.5p) | %boldYellow(%-40.40c{40}) | %boldGreen(%-8.8L)| %cyan(%m) %n"/>-->
<property name="logPattern" value="%date{yyyy-MM-dd HH:mm:ss} | %p | %c | %M:%L | %m%n"/>
<!-- 日志输出编码格式 -->
<property name="logCharset" value="UTF-8"/>
<!--配置控制台的输出-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${logPatternConsoleLog}</pattern>
<charset>${logCharset}</charset>
</encoder>
</appender>
<!--配置文件输出:error-->
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 过滤器,只记录ERROR级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch> <!--如果是匹配,就接受这条规则【整个appender块】,FilterReply类(DENY,NEUTRAL,ACCEPT)-->
<onMismatch>DENY</onMismatch> <!--如果没有匹配,就禁止-->
<!--<onMismatch>NEUTRAL</onMismatch>--> <!--如果没有匹配,就忽略这条规则,看下一个【appender块规则是否接受】-->
</filter>
<encoder>
<pattern>${logPattern}</pattern>
<charset>${logCharset}</charset>
</encoder>
<!--滚动策略:每天一个日志文件-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>${logPath}/%d{yyyy-MM-dd}/error.%d.log</fileNamePattern>
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是30,
则只保存最近30天的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
</appender>
<!--配置文件输出:info-->
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>${logPattern}</pattern>
<charset>${logCharset}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/%d{yyyy-MM-dd}/info.%d.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
</appender>
<!--设置日志级别-->
<root level="info">
<appender-ref ref="consoleLog"/> <!--控制台-->
<appender-ref ref="fileErrorLog"/> <!--error文件-->
<appender-ref ref="fileInfoLog"/> <!--info文件-->
</root>
</configuration>
测试类:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
logger.info("log info");
logger.warn("log warn");
logger.debug("log debug");
}
}
运行结果:
自由组合
有了日志接口和日志实现这两个概念后,我们可以选择更自由的组合,例如在引入如下依赖后:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.26</version>
</dependency>
我们就可以使用 Log4j
作为 SLF4J
的实现了。