spring日志记录(使用切面方式记录)
执行流程图
文章图片
1. 创建pojo类
@Data
@Table(name = "tb_operate_record")
public class OperateRecord {
@Id
private String id;
//记录请求时间
@Column(name = "record_time")
private Date recordTime;
//操作者
private String username;
//请求IP
@Column(name = "request_ip")
private String requestIp;
//操作类型, true操作记录 false异常记录
private Boolean type;
//请求的方法
@Column(name = "request_method")
private String requestMethod;
//自定义注解中的name
@Column(name = "request_annotation_name")
private String requestAnnotationName;
//异常描述
@Column(name = "exception_msg")
private String exceptionMsg;
}
/**
* 系统日志事件
*/
public class OperateRecordEvent extends ApplicationEvent {
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public OperateRecordEvent(Object source) {
super(source);
}
}
2.创建自定义注解
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface LogRecord {
String value() default "";
}
3.创建监听器
/**
* 注解形式的监听,异步监听日志事件
*/
@Component @Slf4j
public class OperateRecordListener {
@Autowired
private OperateRecordService operateRecordService;
@Async @Order @EventListener(OperateRecordEvent.class)
public void saveOperateRecord(OperateRecordEvent event) {
OperateRecord operateRecord = (OperateRecord) event.getSource();
//保存日志
operateRecordService.save(operateRecord);
}
}
4.创建切面类
/**
* 操作日志切面
* 且体面注解得到请求数据 --> 发布监听事件 --> 异步监听日志入库
*/
@Component @Aspect@Slf4j
public class OperateAspect {
// 创建OperateRecord对象
private OperateRecord operateRecord = new OperateRecord();
@Autowired
private ApplicationContext applicationContext;
@Autowired
private RsaKeyProperties properties;
/**
* 定义controller切入点拦截规则,拦截LogRecord注解的方法
*/
@Pointcut("@annotation(com.mayday.common.api.LogRecord)")
public void operateAspect() {}
/**
* 拦截控制层的操作日志
*
* @param joinPoint
*/
@Before(valuehttps://www.it610.com/article/= "https://www.it610.com/article/operateAspect()")
public void recordLog(JoinPoint joinPoint) throws Exception {
//获取request对象
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
operateRecord.setId(String.valueOf(new IdWorker().nextId()));
operateRecord.setRecordTime(new Date());
operateRecord.setRequestIp(request.getRemoteHost());
String username = this.getUsernameByRequest(request);
operateRecord.setUsername(StringUtils.isNotEmpty(username) ? username : "anonymous");
operateRecord.setRequestMethod(joinPoint.getTarget().getClass().getSimpleName() + "." + joinPoint.getSignature().getName());
operateRecord.setRequestAnnotationName(this.getControllerMethodDescription(joinPoint));
}/**
* 返回通知
*
* @param ret
*/
@AfterReturning(returning = "ret", pointcut = "operateAspect()")
public void doAfterReturning(Object ret) {
//处理完请求,返回内容
Result result = Convert.convert(Result.class, ret);
if (result.getFlag()) {
//正常返回
operateRecord.setType(true);
} else {
operateRecord.setType(false);
String resultMsg = result.getMessage();
if ((StringUtils.length(resultMsg) > 10)) {
operateRecord.setExceptionMsg(resultMsg.substring(0, 10));
} else {
operateRecord.setExceptionMsg(resultMsg);
}
}
//发布事件
applicationContext.publishEvent(new OperateRecordEvent(operateRecord));
}/**
* 异常通知
*
* @param e
*/
@AfterThrowing(pointcut = "operateAspect()", throwing = "e")
public void doAfterThrowable(Throwable e) {
//异常
operateRecord.setType(false);
operateRecord.setExceptionMsg(e.getMessage());
//发布事件
applicationContext.publishEvent(new OperateRecordEvent(operateRecord));
}/**
* 通过request对象获取用户名
*
* @param request
* @return
*/
private String getUsernameByRequest(HttpServletRequest request) {
String header = request.getHeader("Authorization");
if (StringUtils.isNotEmpty(header) && header.startsWith("Bearer ")) {
String token = header.replace("Bearer ", "");
Payload payload = JwtUtils.genInfoFromToken(token, properties.getPublicKey(), User.class);
return payload.getUserInfo().getUsername();
}
return null;
}/**
* 获取方法上对应注解的value
*
* @param joinPoint
* @return
* @throws Exception
*/
private String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
//获取连接点目标类型
String targetName = joinPoint.getTarget().getClass().getName();
//获取连接点签名的方法名
String methodName = joinPoint.getSignature().getName();
//获取连接点参数
Object[] args = joinPoint.getArgs();
//根据连接点类的名字获取指定类
Class> targetClass = Class.forName(targetName);
//获取类里面的方法
Method[] methods = targetClass.getMethods();
String valuehttps://www.it610.com/article/= "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class>[] cls = method.getParameterTypes();
if (cls.length == args.length) {
value = https://www.it610.com/article/method.getAnnotation(LogRecord.class).value();
break;
}
}
}
return value;
}
}
5.在相应的类上加上注解 【spring|SpringAop日志记录】
文章图片
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- =======j2ee|spring用注解实现注入的@resource,@autowired,@inject区别
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])