Log4j2.x的简单使用

最近在做项目的过程中,无意中发现,log4j1.x居然存在多线程下出现死锁的问题,这可是很严重的问题,果断改啊。Apache不愧是个有良心的组织,出了log4j2.x版本,不紧解决了死锁问题,还支持异步写日志等。当然,本次只说明一下log4j2.x的简单使用,复杂的使用以后用到再说。

下面直接上代码:

一、引入jar包

在纯Java的项目中,需要引入的jar包

<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.5</version>
		</dependency>

 在web项目中,需要引入的jar包

<!-- slf4j核心包 -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.13</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>1.7.13</version>
			<scope>runtime</scope>
		</dependency>
		<!--核心log4j2jar包 -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.5</version>
		</dependency>
		<!--用于与slf4j保持桥接 -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-slf4j-impl</artifactId>
			<version>2.4.1</version>
		</dependency>
		<!--web工程需要包含log4j-web,非web工程不需要 -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-web</artifactId>
			<version>2.4.1</version>
			<scope>runtime</scope>
		</dependency>

 可以看出来,log4j2.x与log4j1.x相比,增加了很多依赖包

二、Java代码中的使用:

方法一:直接使用log4j的api

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

 

private static Logger logger = LogManager.getLogger(CloudResourceController.class);

 方法二:对log4j进行一次封装

1、封装接口类Logger:

/**
 * 自定义logger接口,避免下次修改log版本后还要修改所有的Java文件
 *
 * @ClassName: Logger   
 * @author chenting
 * @date 2017年7月7日 
 *
 */
public interface Logger {

	/**
	 * Log a message at the DEBUG level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void debug(String msg);

	/**
	 * Log a message at the INFO level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void info(String msg);

	/**
	 * Log a message at the WARN level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void warn(String msg);

	/**
	 * Log a message at the ERROR level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void error(String msg);

	/**
	 * Log an exception (throwable) at the ERROR level with an accompanying
	 * message.
	 * 
	 * @param msg
	 *            the message accompanying the exception
	 * @param t
	 *            the exception (throwable) to log
	 */
	public void error(Object msg, Throwable t);
}

 2、接口实现类:

import org.apache.logging.log4j.LogManager;

/**
 * Logger实现类,避免下次修改log版本后还要修改所有的Java文件
 *
 * @ClassName: LoggerFactory   
 * @author chenting
 * @date 2017年7月7日 
 *
 */
public class LoggerFactory implements Logger{
	
	private org.apache.logging.log4j.Logger logger;
	
	private LoggerFactory(Class<?> clazz){
		this.logger = LogManager.getLogger(clazz);
	}
	private LoggerFactory(String className){
		this.logger = LogManager.getLogger(className);
	}
	
	public synchronized static Logger getLogger(Class<?> clazz) {
		return new LoggerFactory(clazz);
	}
	public synchronized static Logger getLogger(String className) {
		return new LoggerFactory(className);
	}

	/**
	 * Log a message at the DEBUG level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void debug(String msg) {
		this.logger.debug(msg);
	}

	/**
	 * Log a message at the INFO level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void info(String msg) {
		this.logger.info(msg);
	}
	/**
	 * Log a message at the WARN level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void warn(String msg) {
		this.logger.warn(msg);
	}
	/**
	 * Log a message at the ERROR level.
	 * 
	 * @param msg
	 *            the message string to be logged
	 */
	public void error(String msg) {
		this.logger.error(msg);
	}
	/**
	 * Log an exception (throwable) at the ERROR level with an accompanying
	 * message.
	 * 
	 * @param msg
	 *            the message accompanying the exception
	 * @param t
	 *            the exception (throwable) to log
	 */
	public void error(Object msg, Throwable t) {
		this.logger.error(msg, t);
	}
}

3、具体使用:

private static Logger logger = LoggerFactory.getLogger(MainController.class);

 按照上面三个步骤来实现即可

这样做的一个好处是,下次再想改其他的日志的话,只需要更新一下Logger接口的实现类即可,不用再像方法一那样,一个个的修改Java文件。有个坏处就是,没法具体定位到日志具体是在哪个Java文件中输出的,只能看到日志最终是经过LoggerFactory的接口输出的,这个希望有看到的朋友给出出主意。

三、log4j2的配置文件

与log4j1.x不同的是,log4j2.x已经不支持properties类型的配置文件,只支持xml,json等的日志,针对我个人来讲,配置起来2.x比1.x麻烦,或许是对1.x产生依赖了把,废话不多说,上代码:

这里我使用的是xml格式的,文件名log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出, 这一行我设置为OFF,表示不记录log4j2本身的日志 
	monitorInterval: Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。 -->
<Configuration status="off" monitorInterval="1800">

	<Properties>
		<!-- 日志基础路径 -->
		<Property name="BASEPATH">${sys:catalina.base}/logs</Property>
		<!-- 日志文件名称 -->
		<Property name="LOG_FILENAME">cms.log</Property>
		<!-- 日志保存天数 -->
		<Property name="LOG_SAVED_DATE">10d</Property>
		<!-- 日志输出格式 -->
		<Property name="LOG_PATTERN_LAYOUT">%d{yyyy-MM-dd HH:mm:ss.SSS} [ %level ] [ %thread ] %class{36} - %M %L - %msg%xEx%n</Property>
	</Properties>

	<Appenders>
		<!--这个输出控制台的配置 -->
		<Console name="Console" target="SYSTEM_OUT">
			<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
			<ThresholdFilter level="trace" onMatch="ACCEPT"
				onMismatch="DENY" />
			<!-- 输出日志的格式 -->
			<PatternLayout pattern="${LOG_PATTERN_LAYOUT}" />
		</Console>

		<!-- 按天备份一个日志 -->    
        <!-- fileName为生成的文件名,也可以采用相对路径模式,filePattern为时间到达后产生新日志,旧日志的文件名 -->  
		<RollingFile name="RollingFile" fileName="${BASEPATH}/${LOG_FILENAME}" filePattern="${BASEPATH}/${LOG_FILENAME}_%d{yyyy-MM-dd}.log">
			<!-- 日志输出格式 -->
			<PatternLayout pattern="${LOG_PATTERN_LAYOUT}" />
			<Policies>
				<!-- 每1天更新一次,此处查阅网上和官方示例中,都是以小时出现,我测试是以天为单位。(官方文档中说明按item类型是否是小时,但没找到在哪里设置item类型)另有其他各类型策略,请参阅官方文档 -->
				<!-- TimeBasedTriggeringPolicy需要和filePattern配套使用,由于filePattern配置的时间最小粒度是dd天,所以表示每一天新建一个文件保存日志。
				SizeBasedTriggeringPolicy表示当文件大小大于指定size时,生成新的文件保存日志。 -->
				<TimeBasedTriggeringPolicy modulate="true" interval="1" />
			</Policies>
			<!-- 最多备份10天以内的日志,此处为策略限制,Delete中可以按自己需要用正则表达式编写 -->    
        	<!-- DefaultRolloverStrategy字段中加入max="30"经测试是配合SizeBasedTriggeringPolicy限制%i的存在数量,并没有发现是网上流传的是最多保存多少个文件的限制,也或许是我写的有问题 -->    
         	<DefaultRolloverStrategy>
         		<!-- log4j2.5版本之后才支持 -->
        		<Delete basePath="${BASEPATH}" maxDepth="1">
                     <IfFileName glob="${LOG_FILENAME}_*.log" />
                     <!-- 日志保存天数 --> 
                     <IfLastModified age="${LOG_SAVED_DATE}" />
            	</Delete>    
            </DefaultRolloverStrategy>    
		</RollingFile>

	</Appenders>

	<Loggers>
		<!-- 配置日志的根节点 -->
		<!-- 然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
		<root level="debug"><!-- level设置为info后,mybatis就没有SQL日志输出了,暂时未找到原因 -->
			<appender-ref ref="Console" />
			<appender-ref ref="RollingFile" />
		</root>

	<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="INFO"></logger>
        <logger name="org.apache.ibatis.io" level="INFO"></logger>
	<logger name="org.springframework" level="INFO"></logger>
        <logger name="druid.sql.Connection" level="INFO"></logger>
        <logger name="druid.sql.DataSource" level="INFO"></logger>
        <logger name="druid.sql.Statement" level="INFO"></logger>
        <logger name="druid.sql.ResultSet" level="INFO"></logger>

	</Loggers>

</Configuration>

针对Loggers的配置,还可以这么配:

<Loggers>
		<!-- 配置日志的根节点 -->
		<!-- 然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
		<root level="INFO"><!-- level设置为info后,mybatis就没有SQL日志输出了,暂时未找到原因 -->
			<appender-ref ref="Console" />
		</root>
		
		<!-- 普通日志 -->
		<logger name="com.visionvera" level="INFO">
			<appender-ref ref="DnsRollingFile" />
		</logger>
		
		<!-- 心跳日志 -->
		<logger name="heart" level="INFO">
			<appender-ref ref="HeartRollingFile" />
		</logger>
		
		<!-- 屏蔽druid的日志输出 -->
		<logger name="com.alibaba.druid" level="error"></logger>
		
		<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="INFO"></logger>
        <logger name="org.apache.ibatis.io" level="INFO"></logger>
		<logger name="org.springframework" level="INFO"></logger>
        <logger name="druid.sql.Connection" level="INFO"></logger>
        <logger name="druid.sql.DataSource" level="INFO"></logger>
        <logger name="druid.sql.Statement" level="INFO"></logger>
        <logger name="druid.sql.ResultSet" level="INFO"></logger>

	</Loggers>

 这样配的目的是,想让不同业务的日志输出到不同文件中,其中name=“heart”的日志,在代码中需要这么写:

private static Logger hearLogger = LoggerFactory.getLogger("heart");

需要注意的是,log4j2.x版本在servlet2.x版本下,需要在web.xml里面进行配置,servlet3.x的就不用了,具体怎么配,这里不写了,有兴趣的可以自己查看一下。

以上便是我的一点简单的使用,自己留作记录,也希望能帮助到需要的朋友。

猜你喜欢

转载自dove19900520.iteye.com/blog/2383892
今日推荐