- 注意注意:由于使用的是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替换掉新闻的后台管理页面(由于很多页面效果无法实现,采用现成的模板)