SpringBootAOP⾃定义注解异步监听⽅式实现⽇志记录(附源码)
⼀. 功能简介
本⽂主要记录如何使⽤ 注解+aop切⾯+异步监听 的⽅式来实现⽇志记录功能。
主要记录的信息有: 操作⼈,操作IP,⽅法名,参数,消耗时间,⽇志类型,操作类型(操作⽇志和异常⽇志)以及增删改查记录,操作时间等。
主要流程:
AOP切⾯得到请求数据 -> 发布监听事件 -> 异步监听⽇志⼊库
⼆. 项⽬结构
三. 项⽬实战
1.引⼊依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.⾃定义注解
主要标注⽇志的具体⽤处也就是具体操作
package com.xd.pre.log;
import java.lang.annotation.*;
//元注解,定义注解被保留策略,⼀般有三种策略
//1、RetentionPolicy.SOURCE 注解只保留在源⽂件中,在编译成class⽂件的时候被遗弃
//2、RetentionPolicy.CLASS 注解被保留在class中,但是在jvm加载的时候北欧抛弃,这个是默认的声明周期//3、RetentionPolicy.RUNTIME 注解在jvm加载的时候仍被保留
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})//定义了注解声明在哪些元素之前
@Documented
public @interface SysLog {
//定义成员
String descrption()default"";//描述
}
3.AOP切⾯类
AOP切⾯类是最主要的,可以使⽤⾃定义注解或针对包名实现AOP增强。
1)这⾥实现了对⾃定义注解的切点,对使⽤了⾃定义注解的⽅法进⾏AOP切⾯处理;
2)对⽅法运⾏时间进⾏监控;
3)对⽅法名,参数名,参数值,对⽇志描述以及异常信息的优化处理;
4)发布监听事件,⽇志异步⼊库
在⽅法上增加@Aspect 注解声明切⾯,使⽤@Pointcut 注解定义切点,标记⽅法。
package com.xd.pre.log;
import onvert.Convert;
import util.URLUtil;
import a.servlet.ServletUtil;
import com.xd.pre.security.PreUser;
import com.xd.pre.security.util.SecurityUtil;
import com.xd.pre.utils.LogUtil;
import com.xd.pre.utils.R;
slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import t.ApplicationContext;
import org.springframework.stereotype.Component;
import org.t.request.RequestContextHolder;
import org.t.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Objects;
/**
* @Classname SysLogAspect
* @Description 系统⽇志切⾯
* @Author 李号东 lihaodongmail@163git reset --merge
* @Date 2019-04-22 23:52
* @Version 1.0
* ①切⾯注解得到请求数据 -> ②发布监听事件 -> ③异步监听⽇志⼊库
*/
@Slf4j
@Aspect
@Aspect
@Component
public class SysLogAspect {
private com.xd.pre.domain.SysLog sysLog = new com.xd.pre.domain.SysLog();
/**
* 事件发布是由ApplicationContext对象管控的,我们发布事件前需要注⼊ApplicationContext对象调⽤publishEvent⽅法完成事件发布
**/
@Autowired
private ApplicationContext applicationContext;
/***
* 定义controller切⼊点拦截规则,拦截SysLog注解的⽅法
*/
@Pointcut("@annotation(com.xd.pre.log.SysLog)")
public void sysLogAspect() {
}
/***
* 拦截控制层的操作⽇志
* @param joinPoint
* @return
* @throws Throwable
*/
@Before(value = "sysLogAspect()")
public void recordLog(JoinPoint joinPoint) throws Throwable {
// 开始时间
long beginTime = w().toEpochMilli();
HttpServletRequest request = ((ServletRequestAttributes) RequestAttributes())).getRequest(); PreUser securityUser = User();
sysLog.Username());
sysLog.RequestURI()));
sysLog.w());
sysLog.ClientIP(request));
sysLog.Method());
sysLog.Header("user-agent"));
//访问⽬标⽅法的参数可动态改变参数值
Object[] args = Args();
//获取执⾏的⽅法名
sysLog.Signature().getName());
// 类名
sysLog.Target().getClass().getName());
sysLog.Signature().getName());
sysLog.w());
// 参数
sysLog.String(args));
sysLog.ControllerMethodDescription(joinPoint));
long endTime = w().toEpochMilli();
sysLog.setConsumingTime(endTime - beginTime);
}
/**
* 返回通知
* @param ret
* @throws Throwable
*/
@AfterReturning(returning = "ret", pointcut = "sysLogAspect()")
public void doAfterReturning(Object ret) {
/
/ 处理完请求,返回内容
R r = vert(R.class, ret);
if (r.getCode() == 200){
if (r.getCode() == 200){
// 正常返回
sysLog.setType(1);
} else {
sysLog.setType(2);
sysLog.Msg());
}
// 发布事件
applicationContext.publishEvent(new SysLogEvent(sysLog));
}
/**
* 异常通知
* @param e
*/
@AfterThrowing(pointcut = "sysLogAspect()",throwing = "e")
public void doAfterThrowable(Throwable e){
// 异常
sysLog.setType(2);
// 异常对象
sysLog.StackTrace(e));
// 异常信息
sysLog.Message());
// 发布事件
applicationContext.publishEvent(new SysLogEvent(sysLog));
}
}
⽬前使⽤: 前置通知,后置通知,异常通知
事件发布是由ApplicationContext对象管控的,我们发布事件前需要注⼊ApplicationContext对象调⽤publishEvent⽅法完成事件发布4.⽇志实体类
主要记录⽇志的详细信息
package com.xd.pre.domain;
import batisplus.annotation.IdType;
import batisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
perimental.Accessors;
/**
* <p>
* 系统⽇志
* </p>
*
* @author lihaodong
* @since 2019-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SysLog implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO) private Integer id;
/**
* 操作IP
*/
private String requestIp;
/**
* 操作类型 1 操作记录 2异常记录
*/
private Integer type;
/**
springboot aop
* 操作⼈ID
*/
private String userName;
/**
* 操作描述
*/
private String description;
/**
* 请求⽅法
*/
private String actionMethod;
/
**
* 请求url
*/
private String actionUrl;
/**
* 请求参数
*/
private String params;
/**
* 浏览器
*/
private String ua;
/**
* 类路径
*/
private String classPath;
/**
* 请求⽅法
*/
private String requestMethod;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 完成时间
*/
private LocalDateTime finishTime;
/**
* 消耗时间
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论