log4j2教程
<h1>log4j2教程</h1>
<h2>文档修订记录表</h2>
<table>
<thead>
<tr>
<th><strong>修订日期</strong></th>
<th><strong>版数</strong></th>
<th><strong>摘 要</strong></th>
<th><strong>涉及章节</strong></th>
<th><strong>修订者</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>20211117</td>
<td>1.0</td>
<td></td>
<td>ALL</td>
<td>戈峰</td>
</tr>
</tbody>
</table>
<p>[toc]</p>
<h2>1. 简介</h2>
<p>log4j是基于java的日志框架,是Apache Software Foundation的一个开源项目。日志记录是将信息写入控制台、日志文件或数据库的过程,一个系统除了要完成业务上的各项功能,同时出于以下目的需要具有日志记录的能力。</p>
<ul>
<li>故障排除</li>
<li>信息收集</li>
<li>剖析</li>
<li>稽核</li>
<li>产生统计资料</li>
</ul>
<p>记录不仅限于识别软件开发中的错误。 它还可用于检测安全事件,监视策略违规,在出现问题时提供信息,查找应用瓶颈或生成使用情况数据。</p>
<h2>2. 默认配置下的简单示例</h2>
<p>我们写一个Configure类,该类的功能为读取和解析配置文件jdbc.properties。假设我们需要在日志中记录这个文件的地址和这个配置文件里面每一个配置项的详细信息。</p>
<ul>
<li>jdbc.properties</li>
</ul>
<pre><code>jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://120.77.176.239:3306/o2o?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root</code></pre>
<ul>
<li>首先我们需要在项目中引入log4j2</li>
</ul>
<pre><code class="language-xml"><dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency></code></pre>
<ul>
<li>编写Configure类</li>
</ul>
<pre><code class="language-java">package com.doit.log4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Properties;
public class Configure {
private static Logger log = LogManager.getLogger(Configure.class);
public void config() {
log.info("using default jdbc.properties");
config("jdbc.properties");
}
public void config(String resourceName) {
log.info("using config file in classpath:" + resourceName);
try {
Properties prop = new Properties();
prop.load(this.getClass().getClassLoader().getResourceAsStream(resourceName));
log.debug("load properties file success");
for (String key : prop.stringPropertyNames()) {
String value = prop.getProperty(key);
// doSomeConfigWorkUseKeyAndValue(key,value)
log.debug("[properties] " + key + " : " + value);
}
} catch (Exception e) {
log.error("log properties file failed", e);
}
}
}
</code></pre>
<p>在Configure类中,我们使用<code>private static Logger log = LogManager.getLogger(Configure.class);</code>获取到一个与这个类绑定的日志记录器(Logger)实例;我们使用三种Logger实例的方法(info、debug、error)进行日志信息的输出,事实上他们也对应log4j的日志级别。</p>
<p>现在我们写一个类JavaLog4jEx来测试Configure类</p>
<pre><code class="language-java">package com.doit.log4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class JavaLog4jEx {
private static Logger log = LogManager.getLogger(JavaLog4jEx.class);
public static void main(String[] args){
Configure conf = new Configure();
conf.config();
}
}</code></pre>
<p>运行测试,控制台输出:</p>
<pre><code>16:21:11.234 [main] INFO com.doit.log4j.Configure - using default jdbc.properties
16:21:11.237 [main] INFO com.doit.log4j.Configure - using config file in classpath:jdbc.properties
16:21:11.240 [main] DEBUG com.doit.log4j.Configure - load properties file success
16:21:11.240 [main] DEBUG com.doit.log4j.Configure - [properties] jdbc.url : jdbc:mysql://120.77.176.239:3306/o2o?useUnicode=true&characterEncoding=utf8
16:21:11.240 [main] DEBUG com.doit.log4j.Configure - [properties] jdbc.username : root
16:21:11.240 [main] DEBUG com.doit.log4j.Configure - [properties] jdbc.driver : com.mysql.jdbc.Driver
16:21:11.240 [main] DEBUG com.doit.log4j.Configure - [properties] jdbc.password : root</code></pre>
<p>现在我们修改代码传一个不存在的配置文件</p>
<pre><code class="language-java">public static void main(String[] args){
Configure conf = new Configure();
conf.config("noexist.properties");
}</code></pre>
<p>运行测试,控制台输出:</p>
<pre><code>16:48:27.383 [main] INFO com.doit.log4j.Configure - using config file in classpath:noexist.properties
16:48:27.434 [main] ERROR com.doit.log4j.Configure - log properties file failed
java.lang.NullPointerException: null
at java.util.Properties$LineReader.readLine(Properties.java:434)
at java.util.Properties.load0(Properties.java:353)
at java.util.Properties.load(Properties.java:341)
at com.doit.log4j.Configure.config(Configure.java:20)
at com.doit.log4j.JavaLog4jEx.main(JavaLog4jEx.java:13)</code></pre>
<p>可以发现我们在代码中使用info、debug、error方法传入的信息都在控制台打印了出来,除了我们传入的信息,每句日志之前还有一些格式统一的信息:时间、线程名、日志级别、类型名,然而我们并没有配置过日志的输出格式,为什么这些日志信息会以这样的格式输出在控制台上呢?</p>
<p>事实上使用log4j需要我们通过配置文件告诉log4j在什么地方使用日志记录器以什么样的格式记录日志,log4j 2.0以后,其配置文件只能采用.xml, .json或者 .jsn。在默认情况下,系统选择configuration文件的优先级如下:</p>
<ul>
<li>classpath下名为 log4j-test.json 或者log4j-test.jsn文件</li>
<li>classpath下名为 log4j2-test.xml</li>
<li>classpath下名为 log4j.json 或者log4j.jsn文件</li>
<li>classpath下名为 log4j2.xml</li>
</ul>
<p>如果都没有找到,则会按加载默认配置:</p>
<pre><code class="language-xml"><?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration></code></pre>
<p>之前的在控制台打印日志信息的格式就是使用了默认配置的结果。</p>
<h2>3. 组件</h2>
<p>在上一节中我们提到需要在配置文件中告诉Log4J3个要素:什么地方、日志记录器和什么格式,Log4J使用了三个最重要的组件来描述这三个要素,即:</p>
<ul>
<li>
<p>Logger:日志记录器</p>
</li>
<li>
<p>Appender:什么地方</p>
</li>
<li>Layout:什么格式</li>
</ul>
<h3>3.1. Logger</h3>
<p>Logger就是我们直接用来完成日志的工具,并且Logger是有层级结构体系的,这个层次结构和java中package的层次结构是一致的,使用<strong>.</strong>来区分。默认配置中<code><Loggers></code>标签下<code><Root></code>标签对应着rootLogger,它是整个Logger层次结构的根节点,可以通过java代码</p>
<center>```Logger rootLogger = LogManager.getRootLogger();```</center>
<p>来获取。我们在Configure类中写的</p>
<center>``` private static Logger log = LogManager.getLogger(JavaLog4jEx.class);```</center>
<p>代码的真正含义是,当我们在com.doit.log4j这个Logger体系结构下创建了一个名字为com.doit.log4j.Configure的Logger实例,这个实例的根Logger就是rootLogger()。层次关系如下:</p>
<center></center>
<p>rootLogger有下面的规范:</p>
<ul>
<li>rootLogger是没有名字的;</li>
<li>rootLogger是自动存在的;</li>
<li>rootLogger必须设置Level等级;</li>
<li>rootLogger没有名字,所以无法像其他的类一样,可以通过Logger.getLogger(String)得到,他只能通过Logger.getRootLogger方法得到</li>
</ul>
<p>在Logger体系中,名字是Logger实例的唯一标识,也是层次划分的依据,比如:名称为java的Logger就是java.util的父Logger;java.util是java.util.Collection的父Logger。当两个Logger的名字相同,这两个Logger就是同一个Logger实例。我们可以简单的通过一个实例来验证:</p>
<pre><code class="language-java">@Test
public void testLoggerName(){
Logger log1=LogManager.getLogger("a");
Logger log2=LogManager.getLogger("a");
log1.info(log1==log2);
}</code></pre>
<p>控制台输出:</p>
<pre><code>21:43:18.905 [main] INFO a - true</code></pre>
<p>说明Logger自身维护着每一个名字的Logger实例的引用,保证相同名字的Logger在不同地方获取到的实例是一致的,这样就允许我们在统一的代码中配置不同Logger的特性。</p>
<p>在Logger中,非常重要的一个组件,就是Logger的日志级别,即Level。在Log4J中,为我们默认的定义了8种不同的Level级别,即all<trace<debug<info<warn<error<fatal<off;而这8中Level级别又刚好对应着Level类中的8个默认实例:Level.ALL;Level.TRACE;Level.DEBUG;Level.INFO;Level.WARN;Level.ERROR;Level.FATAL和Level.OFF。trace到off这六种日志级别正好对应着Logger中的六个方法,即:</p>
<pre><code class="language-java">public class Logger {
......
// 输出日志方法:
public void trace(Object message);
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message);
// 输出带有错误的日志方法:
public void traceg(Object message, Throwable t);
public void debug(Object message, Throwable t);
public void info(Object message, Throwable t);
public void warn(Object message, Throwable t);
public void error(Object message, Throwable t);
public void fatal(Object message, Throwable t);
// 更通用的输出日志方法:
public void log(Level p, Object message);
......
}</code></pre>
<p>最上面6个方法和中间的6个方法其实是对应的,只是中间的6个方法都带有对应的错误信息。而更下面的log方法,是允许我们直接使用Level类型来输出日志,这给了我们直接使用自定义的Level级别提供了输出日志的方式。换句话说,debug(Object message)其实就是log(Level.DEBUG,message)的简写而已。</p>
<h3>3.2. Appender</h3>
<p>在Log4J中,Appender定义了日志输出的目的地。log4j的默认配置中<code><Appenders></code>标签下定义了一个<console>对应ConsoleAppender,target="SYSTEM_OUT"表示它将把日志信息打印到控制台标准输出中,除了控制台,还可以将日志输出到文件,网络,数据库等等。默认配置中rootLogger下<code><AppenderRef ref="Console"/></code>引用了ConsoleAppender,因为Appender在Logger的层次结构中会被继承,所以我们之前创建的com.doit.log4j.Configure名字的Logger实例会继承rootLogger的Appender,因此我们记录的日志信息会被打印在控制台上。</p>
<p>Appender除了继承性以外还具有追加性。现在我们在log4j2-test.xml配置文件中增加一个Appender:Console2,并且与<Loggers>标签下com.doit.log4j名的Logger绑定。</p>
<pre><code class="language-xml"><?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console1" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<Console name="Console2" target="SYSTEM_OUT">
<PatternLayout pattern="%logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.doit.log4j" level="debug" >
<AppenderRef ref="Console2"/>
</Logger>
<Root level="error">
<AppenderRef ref="Console1"/>
</Root>
</Loggers>
</Configuration></code></pre>
<p>运行以下代码,我们猜想,当使用com.doit.log4j.testAppender2这个Logger做日志的时候,因为这个Logger本身是没有添加任何Appender,所以他会向上查询任何一个添加了Appender的父Logger,即找到了com.doit.log4j这个Logger,最后使用这个Logger完成日志。</p>
<pre><code class="language-java">@Test
public void testAppender2(){
Logger log=LogManager.getLogger("com.doit.log4j.testAppender2");
log.info("log2 info");
log.debug("log2 debug");
}</code></pre>
<p>运行结果如下:</p>
<pre><code>com.doit.log4j.testAppender2 - log2 info
10:25:21.283 [main] INFO com.doit.log4j.testAppender2 - log2 info
com.doit.log4j.testAppender2 - log2 debug
10:25:21.283 [main] DEBUG com.doit.log4j.testAppender2 - log2 debug
</code></pre>
<p>和我们预测的结果不一样。log2 info和log2 debug分别被输出了两次。根据格式可以看出,com.doit.log4j.testAppender2不仅继承了com.doit.log4j的Appender(Console2),还继承了RootLogger的Appender(Console1)。那我们就能大胆的猜测了,Logger上的Appender不光能继承其父Logger上的Appender,更重要的是,他不光只继承一个,而是只要是其父Logger,其上指定的Appender都会追加到这个子Logger之上。在Log4J中,这个特性叫做Appender的追加性。默认情况下,所有的Logger都自动具有追加性。</p>
<p>但是有些时候,我们并不希望Logger具有追加性。比如这里我们想让com.doit.log4j.testAppender2只需要继承com.doit.log4j的Appender,而不想使用root上面的Appender,该怎么做呢?其实很简单,在<Logger>标签中,有一个setAdditivity属性,如果设置setAdditivity为false,则该logger的子类停止追加该logger之上的Appender;如果设置为true,则具有追加性。我们修改配置文件,com.doit.log4j以下级别的Logger将不再使用com.doit.log4j以上级别Logger的Appender,也就不会使用RootLogger的Appender:</p>
<pre><code class="language-xml"><Logger name="com.doit.log4j" level="debug" additivity="false" >
<AppenderRef ref="Console2"/>
</Logger></code></pre>
<p>在运行上面的测试代码,日志打印结果如下:</p>
<pre><code class="language-java">com.doit.log4j.testAppender2 - log2 info
com.doit.log4j.testAppender2 - log2 debug</code></pre>
<p>和我们的预期相符。</p>
<h3>3.3. Layout</h3>
<pre><code>Layout规定了输出日志的格式,这个对象是绑定在Appender之上的,一般在Appender创建的时候指定。我们可以发现之前的配置文件中都使用了<PatternLayout>,如
``` <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> ```
PatternLayout是最常使用的Layout,允许使用标准的输出格式来指定格式化日志消息的样式。这配置定义了一个格式化日志的模式,在这个模式中,有很多以%开头的参数,每一个参数%d{HH:mm:ss.SSS}日志记录时间;第二个参数%t代表运行该日志的线程名称;第三个参数%-5level,首先-5代表这个字符总占用5个位置,level代表日志输出级别;%logger{36}代表输出日志的Logger的名字,最长36个字符;%msg代表输出的日志内容;%n代表分行。</code></pre>
<h2>4. 日志级别</h2>
<p>log4j定义了8个级别的log(除去OFF和ALL 可以说分为6个级别),优先级从低到高依次为OFF>FATAL>ERROR>WARN>INFO>DEBUG>TRACE>ALL:</p>
<ul>
<li>ALL: 最低等级的 用于打开所有日志记录</li>
<li>TRACE: 很低的日志级别 一般不会使用</li>
<li>DEBUG: 指出细粒度信息事件对调试应用程序是非常有帮助的 主要用于开发过程中打印一些运行信息</li>
<li>INFO: 消息在粗粒度级别上突出强调应用程序的运行过程,打印一些你感兴趣的或者重要的信息 这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用 避免打印过多的日志</li>
<li>WARN: 表明会出现潜在错误的情形 有些信息不是错误信息 但是也要给程序员的一些提示</li>
<li>ERROR: 指出虽然发生错误事件 但仍然不影响系统的继续运行,打印错误和异常信息 如果不想输出太多的日志 可以使用这个级别</li>
<li>FATAL: 指出每个严重的错误事件将会导致应用程序的退出,这个级别比较高了 重大错误 这种级别你可以直接停止程序了</li>
<li>OFF: 最高等级的,用于关闭所有日志记录</li>
</ul>
<p>如果将log level设置在某一个级别上 那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN 那么OFF FATAL ERROR WARN 4个级别的log能正常输出,而INFO DEBUG TRACE ALL级别的log则会被忽略</p>
<h2>5. slf4j</h2>
<p>SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,而是通过Facade Pattern提供一些Java logging API,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。作者创建SLF4J的目的是为了替代Jakarta Commons-Logging。
实际上,SLF4J所提供的核心API是一些接口以及一个LoggerFactory的工厂类。在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统。类似于Apache Common-Logging,SLF4J是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。SLF4J提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。</p>
<p>在log4j中获取Logger对象代码:</p>
<pre><code class="language-java">import org.apache.log4j.Logger;</code></pre>
<pre><code class="language-java">private static Logger logger = Logger.getLogger(TestLog4jApplication.class);</code></pre>
<p>而在log4j中获取Logger对象代码:</p>
<pre><code class="language-java">import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;</code></pre>
<pre><code class="language-java">private static Logger logger = LogManager.getLogger(TestLog4j2Application.class);</code></pre>
<p>假如后期改变log实现系统,所有调用log4j的代码都需要进行修改,假如一开始都使用slf4j.Logger,后期将无需修改代码。如下:</p>
<pre><code class="language-java">import org.slf4j.Logger;
import org.slf4j.LoggerFactory;</code></pre>
<pre><code class="language-java">private static Logger logger = LoggerFactory.getLogger(TestLog4jApplication.class);</code></pre>
<pre><code class="language-java">private static Logger logger = LoggerFactory.getLogger(TestLog4j2Application.class);</code></pre>
<p>slf4j还提供trace、debug、info、warn、error等日志接口。</p>
<h2>6. 在spring boot中使用及配置文件详解</h2>
<h3>6.1. 在pom文件中排除springboot默认日志框架logback</h3>
<pre><code class="language-xml"><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency> </code></pre>
<h3>6.2. 在pom文件中引入log4j2依赖</h3>
<pre><code class="language-xml"><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency></code></pre>
<h3>6.3. 配置文件默认名log4j2-spring.xml,若自定义了文件名,需要在application.yml中配置:</h3>
<pre><code class="language-xml">logging:
config: classpath:log4j2-${spring.profiles.active}.xml</code></pre>
<p>这里每个环境都有一个log4j的配置文件,文件名使用不同的后缀。</p>
<h3>6.4. 配置文件模板</h3>
<pre><code class="language-xml"><?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="更换为你的日志存放目录" />
<property name="FILE_NAME" value="更换为你的日志文件名" />
</Properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
<File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Console"/>
</logger>
<!--监控系统信息-->
<!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="Filelog"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
</code></pre>
<h3>6.5. Log4j2配置详解</h3>
<h4>6.5.1 根节点Configuration</h4>
<pre><code>有两个属性:
- status:用来指定log4j本身的打印日志的级别
- monitorinterval:用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5</code></pre>
<p>有两个子节点: Appenders,Loggers(表明可以定义多个Appender和Logger)</p>
<h4>6.5.2 Appenders节点:常见的有三种子节点:Console、RollingFile、File</h4>
<p>Console节点用来定义输出到控制台的Appender.</p>
<ul>
<li>name:指定Appender的名字.</li>
<li>target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.</li>
<li>PatternLayout:输出格式,不设置默认为:%m%n.</li>
</ul>
<p>File节点用来定义输出到指定位置的文件的Appender.</p>
<ul>
<li>name:指定Appender的名字.</li>
<li>fileName:指定输出日志的目的文件带全路径的文件名.</li>
<li>PatternLayout:输出格式,不设置默认为:%m%n.</li>
</ul>
<p>RollingFile节点用来定义超过指定条件自动删除旧的创建新的Appender.</p>
<ul>
<li>name:指定Appender的名字.</li>
<li>fileName:指定输出日志的目的文件带全路径的文件名.</li>
<li>PatternLayout:输出格式,不设置默认为:%m%n.</li>
<li>filePattern : 指定当发生Rolling时,文件的转移和重命名规则.</li>
<li>Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.</li>
<li>TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am.</li>
<li>SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.</li>
<li>DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。</li>
</ul>
<h4>6.5.3 Loggers节点,常见的有两种:Root和Logger.</h4>
<p>Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出</p>
<pre><code>- level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.</code></pre>
<p>Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。</p>
<ul>
<li>level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.</li>
<li>name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.</li>
<li>AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个 - Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。</li>
</ul>