zl程序教程

您现在的位置是:首页 >  其它

当前栏目

JavaDemo——slf4j搭载log4j2

搭载 slf4j Log4J2 JavaDemo
2023-09-11 14:16:28 时间

maven导入:

<dependency>
	    <groupId>org.apache.logging.log4j</groupId>
	    <artifactId>log4j-slf4j-impl</artifactId>
	    <version>2.13.3</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.logging.log4j</groupId>
	    <artifactId>log4j-api</artifactId>
	    <version>2.13.3</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.logging.log4j</groupId>
	    <artifactId>log4j-core</artifactId>
	    <version>2.13.3</version>
	</dependency>

默认名称叫log4j2.xml的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别:All < Trace < Debug < Info < Warn < Error < Fatal < OFF -->
<!-- configuration属性
status:log4j2自己的信息级别(默认OFF)
monitorInterval:自动检测配置变动时间间隔,设置后修改xml保存配置重新加载xml不需重启程序了(最小5s)
-->
<Configuration status="INFO" monitorInterval="5">
	<Properties>
		<!-- 自定义属性,${XXXXXX}引用 -->
		<property name="log_charset">utf8</property>
	</Properties>
	<Appenders>
		<!-- 控制台输出格式,target:SYSTEM_OUT或者SYSTEM_ERR -->
   		<Console name="ConsoleLog" target="SYSTEM_OUT">
     		<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   		</Console>
   		<!-- 单文件日志,append:每次启动的时候是否接着上次的log文件打印或者直接覆盖 -->
	   	<File name="FileLog" fileName="log/file.log" append="false">
	     	<PatternLayout pattern="%-5level|%msg%n" />
	   	</File>
	   	<!-- 滚动文件日志 -->
		<RollingFile name="RollingFileLog" fileName="rollinglog/rolling.log" filePattern="rollinglog/rolling-%d{yyyy-MM-dd_HH.mm.ss}-%i.log">
			<!-- 输出过滤,打印到文件里的日志级别跟Loggers里的配置取交集(要从Loggers里的等级里选符合的)onMatch和onMismatch的值:ACCEPT/DENY/NEUTRAL -->
	     	<!-- <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/> -->
	     	<!-- 多个ThresholdFilter需要放到Filters里,先过滤不需要的日志,注意过滤顺序 -->
	     	<Filters>
	     		<!-- 只打印warn日志 -->
            	<ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
            	<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
	     	<!-- pattern格式
	     	日志时间	%d{yyyy-MM-dd HH:mm:ss.SSS}
	     	线程名字	%t或者%thread
	     	日志名	%logger或%c
	     	类名		%C或%class
	     	方法名	%M或者%method
	     	日志级别	%p或者%level
	     	日志内容	%m或者%msg或者%message
	     	换行		%n
	     	程序启动到打印日志时间ms	%r
	     	日志位置	%l,相当于%c.%M(%F:%L)
	     	文件名	%F
	     	行号		%L
	     	&	&amp;或者&#38;
	     	<	&lt;或者&#60;
	     	>	&gt;或者&#62;
	     	"	&quot;或者&#34;
	     	'	&apos;或者&#39;
	     	%数字1.数字2pattern	数字1:pattern显示的最小字符(不足空格补,>0右对齐,<0左对齐)	数字2:最多字符(超过则从‘后面’保留‘数字2’个字符)
	     	 -->
	     	 <!-- PatternLayout属性
	     	 pattern:日志格式
	     	 header:每个日志文件开始打印时候最开始打印的内容(如果有旧log文件则会在旧文件结尾打印出header的内容)
	     	 footer:每个日志文件的结尾时打印的内容
	     	 charset:设置编码格式,utf-8,gb2312等
	     	 alwaysWriteExceptions:输出异常(默认true)
	     	  -->
	     	<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}][%t][%C.%M:第%L行]%m%n" header="this is header\n" footer="this is footer\n"
	     		charset="${log_charset}" alwaysWriteExceptions="true"/>
	     	<Policies>
	     		<!-- 按时间生成新log,interval:时间间隔(单位跟filePattern里的%d最小精度一致),modulate:true则从0开始计算间隔,false从启动开始计算 -->
	     		<!-- <TimeBasedTriggeringPolicy interval="15" modulate="false"/> -->
	     		<!-- 按文件大小生成新log -->
	     		<SizeBasedTriggeringPolicy size="1kb"/>
	     	</Policies>
	     	<!-- 最多保留文件个数,默认7,也就是上面filePattern里的%i的最大值(当前正在打印的log不算在内) -->
	     	<DefaultRolloverStrategy max="3"/>
		</RollingFile>
		<!-- 据说这个性能更好
		immediateFlush="false":不会立即将日志写进log文件
		 -->
		<RollingRandomAccessFile name="RollingRandomAccessFileLog"
                                 filePattern="rollingrandomlog/%d{yyyyMMdd-HHmmss}-%i.log.gz"
                                 fileName="rollingrandomlog/rollingrandom.log"
                                 immediateFlush="false">
            <PatternLayout charset="${log_charset}" pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] : %m%n" />
            <Filters>
            	<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <Policies>
            	<TimeBasedTriggeringPolicy interval="10" modulate="true"/>
            	<!-- 通过Cron定时器触发日志滚动(上面的filePattern里需要有时间戳)
            	schedule:Cron表达式
            	evaluateOnStartup=true,如果文件最后修改时间跟当前时间之间定时器认为本应该发生滚动就会立即滚动日志 -->
            	<!-- <CronTriggeringPolicy schedule="0 0 2 * * ?" evaluateOnStartup="true"/> -->
            </Policies>
            <DefaultRolloverStrategy>
            	<!-- 删除日志配置
            	basePath:(必须)扫描日志的根目录
            	maxDepth:扫描目录层级,0表示路径本身被扫描,默认1表示根目录下,Integer.MAX_VALUE表示根目录下全部层级
            	followLinks:是否遵循符号链接,默认false(没看懂官网啥意思)
            	 -->
            	<Delete basePath="rollingrandomlog/" maxDepth="1" followLinks="false">
            		<!-- 删掉匹配的文件 -->
            		<IfFileName glob="*.log.gz"></IfFileName>
            		<!-- 删掉超过60s的 -->
            		<IfLastModified age="60s"></IfLastModified>
            		<IfAny>
            			<!-- 但是保留最近10kb的文件或者最近的3个文件 -->
            			<IfAccumulatedFileSize exceeds="10kb"/>
            			<IfAccumulatedFileCount exceeds="3"/>
            		</IfAny>
            	</Delete>
            </DefaultRolloverStrategy>
        </RollingRandomAccessFile>
	</Appenders>
	<Loggers>
		<!-- name:指定类或者包的全路径,additivity:true也将日志写到Root配置的ref里,false只在自己配置的AppenderRef里打日志 -->
		<Logger name="testlogger" level="info" additivity="false">
			<AppenderRef ref="RollingFileLog"/>
		</Logger>
		<Root level="info">
			<AppenderRef ref="ConsoleLog"/>
		 	<AppenderRef ref="FileLog"/>
		 	<AppenderRef ref="RollingRandomAccessFileLog"/>
		</Root>
	</Loggers>
</Configuration>

测试Demo:

MainTestlog2.java文件:

/**
 * 2020年8月20日下午3:36:04
 */
package testlog4j2;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import testlogger.TestLoggerConfig;

/**
 * @author XWF
 *
 */
public class MainTestlog2 {

	private static final Logger logger = LoggerFactory.getLogger("MyLogName");
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Thread(()->{
			MainTestlog2.showlog();
		}).start();
		TestLoggerConfig.showfun("ABC");
	}

	public static void showlog() {
		for(int i=0; i<100; i++) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			logger.info("print info:" + i);
			logger.warn("print warn:" + i);
			logger.error("print error" + i);
		}
	}
}

另一个包下的TestLoggerConfig.java文件:

/**
 * 2020年8月20日下午4:02:28
 */
package testlogger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author XWF
 *
 */
public class TestLoggerConfig {
	
	private static final Logger logger = LoggerFactory.getLogger(TestLoggerConfig.class);
	
	public static int showfun(String str) {
		for(int i=0; i<100; i++) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			logger.info("+++++" + str + "info:" + i);
			logger.warn("+++++" + str + "warn:" + i);
			logger.error("+++++" + str + "error" + i);
		}
		return 1;
	}
	
}

为了将log4j2.xml文件放到jar包外面方便修改调整,增加一个log4j2.component.properties文件到resource里并打包到jar里用来指定xml文件位置;

配置文件log4j2.component.properties:

log4j2.loggerContextFactory=org.apache.logging.log4j.core.impl.Log4jContextFactory
log4j.configurationFile=./log4j2.xml

eclipse里的目录结构:

Demo运行结果:

控制台:

file.log

rolling.log

rollingrandom.log

参考:

https://www.cnblogs.com/new-life/p/9246143.html

https://blog.csdn.net/luoxiang183/article/details/79281886?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.channel_param

https://blog.csdn.net/saya0/article/details/107334015/

https://blog.csdn.net/qq_24879495/article/details/78061388

https://blog.csdn.net/zhang168/article/details/46814489

https://www.cnblogs.com/frankwin608/p/log4j2.html

https://www.cnblogs.com/jessezeng/p/5144317.html

官网https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy