本文主要介绍Log4j2记录日志到MySQL
一、创建数据库和表
1、创建log数据库:logs
2、创建日志表
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for log_table
-- ----------------------------
DROP TABLE IF EXISTS `log_table`;
CREATE TABLE `log_table` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`log_date` datetime DEFAULT NULL COMMENT '日志日期时间',
`log_level` varchar(32) DEFAULT NULL COMMENT '日志级别',
`log_class` varchar(255) DEFAULT NULL COMMENT '日志所在的类',
`line_number` int(255) DEFAULT NULL COMMENT '在类中的行数',
`log_detail` longtext COMMENT '日志详情',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
二、项目配置
1、添加依赖
<!--用于日志存储,不引用打包时会找不到JDBCAppender -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
#log数据源
log.datasource.url=jdbc:mysql://localhost:3306/logs?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true
log.datasource.username=root
log.datasource.pwd=root
log.datasource.driverClassName=com.mysql.jdbc.Driver
3、创建连接工厂类,继承JDBCAppender,由于Spring通过new的对象无法通过注解加载配置文件中的参数,所有需要用到Properties对象,所以创建一个工具类PropertiesUtil,获取log4j2.properties文件里的值
package com.iyungu.biss.manage.configurer;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.wall.violation.ErrorCode;
import com.iyungu.biss.manage.common.utils.PropertiesUtil;
import org.apache.log4j.jdbc.JDBCAppender;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @Author: yangzhiwei@iyungu.com
* @Description:
* @Date: 2019/4/17
* @Modified By:
*/
public class LogConnectionFactory extends JDBCAppender {
private static String resource = "log4j2-log.properties";
private static String url = PropertiesUtil.getProperty(resource, "log.datasource.url");
private static String driverClassName = PropertiesUtil.getProperty(resource, "log.datasource.driverClassName");
private static String username = PropertiesUtil.getProperty(resource, "log.datasource.username");
private static String psw = PropertiesUtil.getProperty(resource, "log.datasource.pwd");
//Druid数据源
private DruidDataSource dataSource;
private static LogConnectionFactory logConnectionFactory;
public LogConnectionFactory() {
super();
}
/**
* 如果数据库连接对象不为空和没有被关闭的话,关闭数据库连接
* @param con
*/
@Override
protected void closeConnection(Connection con) {
try {
if (con != null && !con.isClosed()) {
con.close();
}
} catch (SQLException e) {
errorHandler.error("Error closing MyJDBCAppender.closeConnection() 's connection", e, ErrorCode.HINT_NOT_ALLOW);
}
}
/**
* 建立数据库连接
* @return
* @throws SQLException
*/
@Override
protected Connection getConnection() throws SQLException {
if(dataSource == null) {
Properties result = new Properties();
result.put("driverClassName", driverClassName);
result.put("url", url);
result.put("username", username);
result.put("password", psw);
try {
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(result);
} catch (Exception e) {
// Druid数据库源对象产生失败后,取消初始化
try {
uninitialize();
} catch (Exception e2) {
}
}
}
return dataSource.getConnection();
}
/**
* 取消初始化
*/
public void uninitialize() {
try {
if (dataSource != null) {
dataSource.close();
}
} catch (Exception e) {
} finally {
super.close();
}
}
/**
* 调用数据库连接
* @return
* @throws SQLException
*/
public static Connection getDataSourceConnection() throws SQLException {
if (logConnectionFactory == null) {
logConnectionFactory = new LogConnectionFactory();
}
return logConnectionFactory.getConnection();
}
}
4、创建PropertiesUtil类
package com.iyungu.biss.manage.common.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
public class PropertiesUtil {
/**
* 读取properties文件
* @param resource 文件名称
* @return
*/
public static Properties getProperties(String resource){
Properties properties = new Properties();
try {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
properties.load(is);
} catch (IOException ioe) {
ioe.printStackTrace();
throw new RuntimeException(ioe);
}
return properties;
}
/**
* 获取property
* @param key key
* @return value
*/
public static String getProperty(String resource,String key){
Properties properties = PropertiesUtil.getProperties(resource);
return properties.getProperty(key);
}
/**
* 获取getPropertyNew
* @param key key
* @return value
*/
public static String getPropertyNew(String resource,String key){
Properties properties = new Properties();
try {
InputStreamReader is = new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource), "UTF-8");
properties.load(is);
} catch (IOException ioe) {
ioe.printStackTrace();
throw new RuntimeException(ioe);
}
return properties.getProperty(key);
}
/**
* 获取匹配的属性列表
* @param resource 资源文件名称
* @param prefix 匹配的前缀字符串
* @return 匹配的结果存入List
*/
public static List getMatchProperties4List(String resource,String prefix){
Properties properties = PropertiesUtil.getProperties(resource);
List list = new ArrayList();
Iterator it = properties.entrySet().iterator();
Object key = null;
Object value = null;
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
key = entry.getKey();
if(key.toString().startsWith(prefix)){
value = entry.getValue();
list.add(value);
}
}
return list;
}
}
5、配置log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--设置log4j的自身日志级别为warn,配置自动检测时间间隔为30秒-->
<Configuration status="WARN" monitorInterval="30">
<properties>
<property name="LOG_HOME">logs</property>
<!--配置日志表名-->
<property name="LOG_TABLE_NAME">log_table</property>
</properties>
<Appenders>
<!--配置控制台日志-->
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %level %logger{36}@%method:%line - %msg%n"/>
</Console>
<!--配置日志写入文件-->
<RollingRandomAccessFile name="infoLog" fileName="${LOG_HOME}/log.log"
filePattern="${LOG_HOME}/log.%d{yyyy-MM-dd}-%i.log.gz" append="true">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %level %logger{36}@%method:%line - %msg%n"/>
<Policies>
<!-- 对应 filePattern维度,此处为天数-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingRandomAccessFile>
<JDBC name="databaseAppender" tableName="${LOG_TABLE_NAME}">
<!--配置数据库连接com.iyungu.biss.xxx.configurer.LogConnectionFactory-->
<ConnectionFactory class="com.iyungu.biss.xxx.configurer.LogConnectionFactory" method="getDataSourceConnection" />
<Column name="log_date" pattern="%d{yyyy-MM-dd HH:mm:ss}"/>
<Column name="log_level" pattern="%p" />
<Column name="log_class" pattern="%c" />
<Column name="line_number" pattern="%L"/>
<Column name="log_detail" pattern="%m"/>
</JDBC>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="console"/>
<!--<AppenderRef ref="infoLog" />-->
<AppenderRef ref="databaseAppender"/>
</Root>
<logger name="org.springframework" level="INFO"> <!--spring日志-->
<AppenderRef ref="infoLog" />
</logger>
<logger name="org.mybatis" level="info" additivity="false"> <!--myBatis日志-->
<!--<AppenderRef ref="infoLog" />-->
<AppenderRef ref="databaseAppender"/>
</logger>
<Logger name="com.iyungu.biss" level="info" additivity="false"> <!--业务日志-->
<!--<AppenderRef ref="infoLog" />-->
<AppenderRef ref="databaseAppender"/>
</Logger>
</Loggers>
</Configuration>