springboot项目练习九 整合log4j2+aop完成新增方法日志信息记录

  • 注意注意:由于使用的是springboot2.0.5版本,故采用log4j2进行日志采集(起初尝试log4j没有成功网上说1.5版本以上得使用log4j2 ,具体原因也未进行深究。知道的小伙伴可以留言告诉一下,大家一起学习)
  • 由于springboot默认使用的是spring-boot-starter-logging这个,需将此依赖排除
  • 起初想在用户请求数据的时候进行日志记录,但由于查询请求,往往存在数据重复,故将日志记录放在add方法前。
  • 使用aop 在add方法前加入前置通知,从JoinPoint对象中获取方法入参,将入参拼接为字符串写入日志文件中

1 导入log4j的依赖和aop的依赖,排除spring-boot-starter-logging这个依赖(另由于项目中使用到common的lang包,将依赖也一并加入)

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
</dependency>
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
	    <groupId>commons-lang</groupId>
	    <artifactId>commons-lang</artifactId>
	    <version>2.6</version>
</dependency>
<dependency>
			<!-- aop -->
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

2 配置log4j2.xml文件,springboot log4j2默认的文件名称

log4j的配置的详细讲解可从https://www.cnblogs.com/yudar/p/5113655.html这篇博客中查看。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="1" status="ERROR" strict="true" name="LogConfig">
    <Properties>
        <Property name="logbasedir">F:/springboot/springboot_solr/src/main/resources/logs/</Property>
        <Property name="log.layout"> %5p [%t] %d{yyyy-MM-dd HH:mm:ss} %m%n</Property>
    </Properties>
    <Appenders>
   <Console name="Console" target="SYSTEM_OUT">
          
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 输出日志的格式 -->
            <PatternLayout pattern="${log.layout}"/>
           
        </Console>
       <RollingFile name="sinfo" fileName="${logbasedir}/news.log" Append="true" 
       			filePattern = "${logbasedir}/news-%d{yyyy-MM-dd}.log"  ImmediateFlush="true">
			<PatternLayout>
                <pattern>${log.layout}</pattern>
                <Charset>UTF-8</Charset>
            </PatternLayout>
             <Policies>
            	 <SizeBasedTriggeringPolicy size="10 MB"/>
            	 <DefaultRolloverStrategy max="20"/>
            </Policies>
       
       </RollingFile>
    </Appenders>

    <Loggers>

        <Root level="info">
        	 <appender-ref ref="Console"/>
        </Root>
        <logger name="com.gc.aop" level="info" includeLocation="true" additivity="true">
            <appender-ref ref="sinfo"/>
        </logger>

    </Loggers>

</Configuration>

3 编写aop类在com.gc.aop包下新建LogAop类并标注为切面类增加@Component交给spring进行管理

package com.gc.aop;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.gc.utils.PageBean;

/**
 * 日志请求aop
 * 拦截查询方法 将请求数据和返回数据进行拦截 
 * 配置的log4j2 的日志级别是info 在这也使用这种方式进行日志的记录
 * @author gc
 *       *         com.gc.solr.*.getByPage(..)
 *    *              返回值任意     
 *    com.gc.solr     包名                           
 *    *              类名任意      
 *    getByPage      方法名  
 *    (..)           参数任意 
 */
@Aspect
@Component
public class LogAop {
	 private final Logger logger = LogManager.getLogger(LogAop.class);; 
	 private ObjectMapper objectMapper = new ObjectMapper(); // jackJson
	private String requestPath = null ; // 请求地址 
	private Map<?,?> inputParamMap = null ; // 传入参数
	private HttpServletRequest request = null;
	private String  host="";
	private String  method="";
	/**
	 *  @Pointcut 切入点
	 */
//	@Pointcut(value="execution(* com.gc.solr.*.getByPage(..))") //切入点表达式 
//	public void queryLog(){};
	
	/**
	 * 前置通知 
	 * 拦截方法请求  封装
	 * 获取request对象
	 * 从requet对象获取请求参数
	 * 请求地址
	 * @param joinPoint
	 * @throws IOException 
	 */
//	@Before(value="queryLog()")
	public  void before(JoinPoint joinPoint) throws IOException{
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes re = (ServletRequestAttributes)requestAttributes;  
        request = re.getRequest();
        StringBuffer  buffer = new StringBuffer();
        inputParamMap =  request.getParameterMap();
        requestPath= request.getRequestURL().toString(); // 请求地址
        host = request.getRemoteHost();
        method = request.getMethod();
        buffer.append("inputParamMap:"+objectMapper.writeValueAsString(inputParamMap)+"\t");
        buffer.append("requestPath:"+requestPath+"\t");
        buffer.append("host:"+host+"\t");
        buffer.append("method:"+method+"\t");
    	logger.info("requestMessage:"+buffer.toString());
        
	}
	/**
	 * 后置通知 
	 * 获取相应结果
	 * @param joinPoint
	 * @throws IOException 
	 */
//	@AfterReturning(returning="page", pointcut="queryLog()")
	@After(value="queryLog")
	public void after(JoinPoint joinPoint,Object page) throws IOException{
		StringBuffer  buffer = new StringBuffer();
		buffer.append("signatureName:"+joinPoint.getSignature().getName());
		buffer.append("methodName:"+joinPoint.getSignature().getName());
		if(page instanceof PageBean){
			PageBean<?> pageBean = (PageBean<?>)page;
			buffer.append("currentPage:"+pageBean.getCurrentPage()+"\t");
			buffer.append("pageSize:"+pageBean.getPageSize()+"\t");
			if(pageBean.getRows()!=null && pageBean.getRows().size()>0){
				buffer.append(objectMapper.writeValueAsString(pageBean.getRows()));
			}
		}else{
			buffer.append(objectMapper.writeValueAsString(page));
		}
		logger.info("resultData:"+buffer.toString());
	}
	
	
	/**
	 *  @Pointcut 切入点
	 *  使用前置通知  拦截方法得到方法入参 对方法入参进行日志记录完成日志文件的存储    
        和上面不同的是 add* 这个表示方法名为add开头 后面任意
	 */
	@Pointcut(value="execution(* com.gc.solr.*.add*(..))") //新增新闻切入点
	public void addLog(){};
	
	/**
	 * addLog 匹配新增新闻的
	 * 在新增之前对新闻信息进行日志记录
	 * @param joinPoint
	 * @throws IOException
	 */
	@Before(value="addLog()")
	public  void beforeAddLog(JoinPoint joinPoint) throws IOException{
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes re = (ServletRequestAttributes)requestAttributes;  
        request = re.getRequest();
        requestPath= request.getRequestURL().toString(); // 请求地址
        host = request.getRemoteHost();
        method = request.getMethod();
        StringBuffer  buffer = new StringBuffer();
        buffer.append("requestPath:"+requestPath+"\t");
        buffer.append("host:"+host+"\t");
        buffer.append("host:"+host+"\t");
        buffer.append("method:"+method+"\t");
        buffer.append("signatureName:"+joinPoint.getSignature().getName()+"\t");
		buffer.append("methodName:"+joinPoint.getSignature().getName()+"\t");
        Object[] args = joinPoint.getArgs(); // 获取参数
        if(null!=args && args.length>0){
        	for (Object object : args) {
				if(object instanceof List){
					buffer.append(objectMapper.writeValueAsString(object)); // 转为json数据
				}
			}
        }
    	logger.info("requestMessage:"+buffer.toString()); // 拼接字符串完成日志记录
	}	
}

日志框架的整合就完成了会在项目指定目录下生成news.log文件

日志信息已成功写入。日志文件的配置和写入日志的不熟悉,在配置文件中RollingRandomAccessFile使用这个配置的时候,日志信息需要等一会才进行写入,换成RollingFile后文件就能正常写入,对这块不是很熟悉。等几天好好研究一下。

现在项目将日志信息也成功记录,下面将在项目根目录下生成的json文件,在这之前需要做以下几步:

  • 创建数据库和表
  • 整合数据库 和pageHelper完成数据库层的分页查询
  • 编写文件递归类,传入该文件目录对文件解析,使用线程同步的方式将解析的数据插入数据库。对数据进行统一管理
  • 修改页面效果,使用hui-admin替换掉新闻的后台管理页面(由于很多页面效果无法实现,采用现成的模板)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Master_slaves

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值