log4j2 记录信息到数据库

58 篇文章 0 订阅
45 篇文章 0 订阅

定义了一个切面 Spring Aop的添加了注解的设置userId等

自定义注解:

package com.pinyu.system.global.ann;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 日志切面注解
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {

    /**
     * 该注解作用于方法上时需要备注信息
     */
    String remark() default "";
    String operType() default "";
}

切面:

package com.pinyu.system.global.aspect;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.pinyu.system.dao.OperationLogDao;
import com.pinyu.system.entity.UserEntity;
import com.pinyu.system.global.ann.MethodLog;
import com.pinyu.system.utils.SessionUtils;

/**
 * @author ypp 创建时间:2018年10月9日 上午10:37:34
 * @Description: TODO(日志切面)
 */
@Component
@Aspect
public class OperationLogAspect {

	protected Logger logger = LogManager.getLogger(OperationLogAspect.class);

	@Autowired
	private OperationLogDao logDao;

	public OperationLogAspect() {
		logger.info("用户操作日志");
	}

	/**
	 * 切点
	 */
	@Pointcut("@annotation(com.pinyu.system.global.ann.MethodLog)")
	public void methodCachePointcut() {
	}

	/**
	 * 切面
	 *
	 * @param point
	 * @return
	 * @throws Throwable
	 */
	@Around("methodCachePointcut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {

		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		String ip = getIp(request);
		UserEntity loginUser = SessionUtils.getLoginUser(request);
		ThreadContext.put("userId",String.valueOf(loginUser.getId()));
		ThreadContext.put("creater", loginUser.getRealName());
		ThreadContext.put("createUserName", loginUser.getUserName());
		ThreadContext.put("ip", ip);
		String methodRemark = getMthodRemark(point);
		Object[] method_param;

		Object object;
//		OperationLogEntity optLog = new OperationLogEntity();
//		optLog.setExFlag(OperationLogEntity.EX_FALSE);
//		try {
//			method_param = point.getArgs(); // 获取方法参数
//			// String param=(String) point.proceed(point.getArgs());
			object = point.proceed();
//		} catch (Exception e) {
//			// 异常处理记录日志..log.error(e);
//			StringWriter stringWriter = new StringWriter();
//			PrintWriter writer = new PrintWriter(stringWriter);
//			e.printStackTrace(writer);
//			StringBuffer buffer = stringWriter.getBuffer();
//			optLog.setExFlag(OperationLogEntity.EX_TRUE);
//			optLog.setExceptionMsg(buffer.toString());
//			throw e;
//		}
//		optLog.setCreaterId(loginUser.getId());
//		optLog.setIp(ip);
//		optLog.setCreater(loginUser.getRealName());
//		optLog.setCreateUserName(loginUser.getUserName());
//		optLog.setOperation(methodRemark);
//		optLog.setCreateDate(new Date());
//		logDao.add(optLog);
		return object;

	}

	/**
	 * 获取请求ip
	 *
	 * @param request
	 * @return
	 */
	public static String getIp(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
//		String ip = request.getHeader("X-Forwarded-For");
//		if (StringUtils.isBlank(ip) || ip.length() == 0 || ip.equals("unKnown")) {
//
//		}
//
//		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
//			int index = ip.indexOf(",");
//			if (index != -1) {
//				return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip.substring(0, index);
//			} else {
//				return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
//			}
//		}
//		ip = request.getHeader("X-Real-IP");
//		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
//			return ip;
//		}
//		return request.getRemoteAddr().equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
	}

	/**
	 * 获取方法中的中文备注
	 *
	 * @param joinPoint
	 * @return
	 * @throws Exception
	 */
	public static String getMthodRemark(ProceedingJoinPoint joinPoint) throws Exception {

		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();

		Class targetClass = Class.forName(targetName);
		Method[] method = targetClass.getMethods();
		String methode = "";
		for (Method m : method) {
			if (m.getName().equals(methodName)) {
				Class[] tmpCs = m.getParameterTypes();
				if (tmpCs.length == arguments.length) {
					MethodLog methodCache = m.getAnnotation(MethodLog.class);
					if (methodCache != null) {
						methode = methodCache.remark();
					}
					break;
				}
			}
		}
		return methode;
	}
}

SQL:

/*
Navicat MySQL Data Transfer

Source Server         : 211.149.199.68
Source Server Version : 50723
Source Host           : 211.149.199.68:3306
Source Database       : mypinyu

Target Server Type    : MYSQL
Target Server Version : 50723
File Encoding         : 65001

Date: 2018-11-01 17:20:59
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for sys_logs
-- ----------------------------
DROP TABLE IF EXISTS `sys_logs`;
CREATE TABLE `sys_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `class` varchar(100) DEFAULT NULL COMMENT '日志类',
  `function` varchar(100) DEFAULT NULL COMMENT '执行的方法名',
  `level` varchar(100) DEFAULT NULL COMMENT '日志级别',
  `logger` varchar(100) DEFAULT NULL,
  `message` text COMMENT '日志内容',
  `create_date` timestamp NULL DEFAULT NULL COMMENT '时间',
  `ip` varchar(255) DEFAULT NULL COMMENT 'IP地址',
  `user_id` varchar(255) DEFAULT NULL,
  `create_user_name` varchar(255) DEFAULT NULL,
  `creater` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3519 DEFAULT CHARSET=utf8 COMMENT='系统日志';

代码 :

package com.pinyu.system.global.config.log4j2;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.springframework.stereotype.Component;

import com.pinyu.system.utils.SystemPropertiesUtils;


/** 
* @author ypp
* 创建时间:2018年11月1日 下午2:33:44 
* @Description: TODO(log4j2日志存储到数据库) 
*/
@Component
public class ConnectionFactory {
	
		private static interface Singleton {  
	       final ConnectionFactory INSTANCE = new ConnectionFactory();  
	    }  
	   
	   private final DataSource dataSource;  
	   
	   private ConnectionFactory() {  
	             try {  
	           Class.forName(SystemPropertiesUtils.getDataSourceDriverClassName());  
	       } catch (ClassNotFoundException e) {  
	           e.printStackTrace();  
	           System.exit(0);  
	       }  
	              
	       Properties properties = new Properties();  
	       properties.setProperty("user", SystemPropertiesUtils.getDataSourceUserName());  
	       properties.setProperty("password", SystemPropertiesUtils.getDataSourcePassword());   
	   
	       GenericObjectPool<PoolableConnection>pool = new GenericObjectPool<PoolableConnection>();  
	       DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(  
	    		   SystemPropertiesUtils.getDataSourceUrl(),properties  
	       );  
	       new PoolableConnectionFactory(connectionFactory, pool, null, null, false, true);  
	       this.dataSource = new PoolingDataSource(pool);  
	    }  
	   
	   public static Connection getDatabaseConnection() throws SQLException {  
	       return Singleton.INSTANCE.dataSource.getConnection();  
	   }  
}

用的dbcp连接池

log4j2配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出 -->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数 -->
<Configuration status="WARN" monitorInterval="30">
	<!--全局属性 -->
	<Properties>
		<Property name="LOG_FILE_PATH">D:/apache-tomcat-8.5.33/logs</Property>
		<!-- linux日志存放路径 <Property name="LOG_FILE_PATH">/usr/logs</Property> -->
		<Property name="PATTERN_FORMAT">%d{yyyy-MM-dd HH:mm:ss} %-5level %class{36} %L
			%M - %msg%xEx%n</Property>
	</Properties>

	<Appenders>
		<!--输出到控制台 -->
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout pattern="${PATTERN_FORMAT}" />
		</Console>


		<!--输出到文件 用来定义超过指定大小自动删除旧的创建新的的Appender. -->
		<RollingFile name="RollingInfoFile" fileName="${LOG_FILE_PATH}/info.log"
			filePattern="${LOG_FILE_PATH}/$${date:yyyyMM}/info-%d{yyyyMMdd}-%i.log.gz">
			<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
			<Filters>
				<ThresholdFilter level="warn" onMatch="DENY"
					onMismatch="NEUTRAL" />
				<ThresholdFilter level="info" onMatch="ACCEPT"
					onMismatch="DENY" />
			</Filters>

			<PatternLayout>
				<pattern>${PATTERN_FORMAT}</pattern>
			</PatternLayout>

			<Policies>
				<!-- rollover on startup, daily and when the file reaches 10 MegaBytes -->
				<OnStartupTriggeringPolicy />
				<SizeBasedTriggeringPolicy size="100 MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
		</RollingFile>

		<!--输出警告日志到文件 -->
		<RollingFile name="RollingWarnFile" fileName="${LOG_FILE_PATH}/warn.log"
			filePattern="${LOG_FILE_PATH}/$${date:yyyyMM}/warn-%d{yyyyMMdd}-%i.log.gz">
			<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
			<Filters>
				<ThresholdFilter level="error" onMatch="DENY"
					onMismatch="NEUTRAL" />
				<ThresholdFilter level="warn" onMatch="ACCEPT"
					onMismatch="DENY" />
			</Filters>

			<PatternLayout>
				<pattern>${PATTERN_FORMAT}</pattern>
			</PatternLayout>

			<Policies>
				<!-- rollover on startup, daily and when the file reaches 10 MegaBytes -->
				<OnStartupTriggeringPolicy />
				<SizeBasedTriggeringPolicy size="100 MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
		</RollingFile>

		<!--输出错误日志到文件 -->
		<RollingFile name="RollingErrorFile" fileName="${LOG_FILE_PATH}/error.log"
			filePattern="${LOG_FILE_PATH}/$${date:yyyyMM}/error-%d{yyyyMMdd}-%i.log.gz">
			<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
			<ThresholdFilter level="error" onMatch="ACCEPT"
				onMismatch="DENY" />

			<PatternLayout>
				<pattern>${PATTERN_FORMAT}</pattern>
			</PatternLayout>

			<Policies>
				<!-- rollover on startup, daily and when the file reaches 10 MegaBytes -->
				<OnStartupTriggeringPolicy />
				<SizeBasedTriggeringPolicy size="100 MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
		</RollingFile>
		<!--保存到数据库配置文件 -->
		<JDBC name="DatabaseAppender" tableName="sys_logs">
			<ConnectionFactory
				class="com.pinyu.system.global.config.log4j2.ConnectionFactory"
				method="getDatabaseConnection" />
			<!-- 方法名 -->
			<Column name="function" pattern="%M" />
			<!-- 日志级别 -->
			<Column name="level" pattern="%level" />
			<Column name="logger" pattern="%logger" />
			<!-- 类 -->
			<Column name="class" pattern="%C" />
			<!-- 时间 -->
			<Column name="create_date" pattern="%d{yyyy-MM-dd hh:mm:ss}" />
			<!-- 日志内容 -->
			<Column name="message" pattern="%message" />
			
			<Column name="user_id" pattern="%X{userId}" />
			<Column name="creater" pattern="%X{creater}" />
			<Column name="ip" pattern="%X{ip}" />
			<Column name="create_user_name" pattern="%X{createUserName}" />
		</JDBC>
	</Appenders>

	<Loggers>

		<!--过滤掉spring和mybatis的一些无用的DEBUG信息 -->
		<Logger name="org.springframework" level="INFO" />
		<Logger name="org.mybatis" level="INFO" />

		<!-- LOG "com.luis*" at TRACE level -->
		<Logger name="com.luis" level="INFO" />

		<!-- LOG everything at INFO level -->
		<Root level="ALL">
			<AppenderRef ref="Console" />
			<AppenderRef ref="RollingInfoFile" />
			<AppenderRef ref="RollingWarnFile" />
			<AppenderRef ref="RollingErrorFile" />
			<AppenderRef ref="DatabaseAppender"/>
		</Root>
	</Loggers>

</Configuration>

注意Root要配置上面数据库DatabaseAppender的信息,其他东西都比较简单。但是有个问题,所有的日志都记录到数据库了,并不能满足实际需求。数据库是可以保存日志信息了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值