直接上代码:
package com.xiyuan.cluster.middle.interceptor;
import com.alibaba.fastjson.JSON;
import com.xiyuan.cluster.middle.common.GlobalExceptionHandler;
import com.xiyuan.cluster.middle.entity.SysLog;
import com.xiyuan.cluster.middle.service.ISysLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author jerry
* @desc 记录日志
* @datetime 2023/07/31
*/
@Slf4j
@Component
@Aspect
public class LogAop {
private static final Logger logger = LoggerFactory.getLogger(LogAop.class);
/**
* 全局异常处理类全限定名
*/
private String exceptionAdviceName = GlobalExceptionHandler.class.getName();
@Autowired
private HttpServletRequest request;
@Autowired
private ISysLogService logService;
//定义日志捕获范围 全局controller接口参数
// @Pointcut("execution(* com.xiyuan.cluster.middle.controller..*.*(..)) || execution(* com.xiyuan.cluster.middle.common.GlobalExceptionHandler.*(..))")
@Pointcut("execution(* com.xiyuan.cluster.middle.controller..*.*(..)))")
public void logAroundPointCut() {
}
/**
* controller层入参日志记录
*/
@Around("logAroundPointCut()")
public Object intoControllerLog(ProceedingJoinPoint point) throws Throwable {
// 目标方法所在类全限定名
String targetName = point.getSignature().getDeclaringType().getName();
String className = ClassUtils.getShortName(targetName);
// 目标方法名
String methodName = point.getSignature().getName();
StringBuilder reqStr = new StringBuilder(300);
String phone = (String) request.getAttribute("phone");
try {
if (targetName.equals(exceptionAdviceName)) {
// controller参数解析异常不会进入目标方法, 而直接请求异常处理器
logger.error("全局日志【{}.{}】接口调用异常,用户手机号:{},异常信息:{}", className, methodName, phone, "请求异常, 未进入controller");
} else {
// 获取请求参数
Object[] args = point.getArgs();
String[] paramsName = ((MethodSignature) point.getSignature()).getParameterNames();
//记录入参4
if (args != null && paramsName != null && args.length > 0 && paramsName.length > 0) {
for (int i = 0; i < paramsName.length; i++) {
reqStr.append(" ").append(paramsName[i]).append(" = ").append(args[i]).append(",");
}
reqStr.deleteCharAt(reqStr.length() - 1);
}
logger.info("全局日志【{}.{}】接口开始调用,用户手机号:{},入参:{}", className, methodName, phone, reqStr);
}
} catch (Exception e) {
e.printStackTrace();
logger.error("全局日志入参处理异常:{}", e.getMessage());
}
// 调用目标方法
Object result = point.proceed();
logger.info("全局日志【{}.{}】接口调用结束, 入参:{}, 出参:{}", className, methodName, reqStr, JSON.toJSONString(result));
return result;
}
/**
* 异常通知: 对目标对象发生异常下进行增强,有异常就执行,没有就不执行
* 作用:目标代码出现异常,记录异常日志
*/
@AfterThrowing(value = "execution(* com.xiyuan.cluster.middle.controller..*.*(..)))", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
try {
SysLog sysLog = new SysLog();
String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
logger.warn("保存错误日志开始【{}.{}】", className, methodName);
StringBuilder reqStr = new StringBuilder(300);
String respStr = "";
Object[] args = joinPoint.getArgs();
String[] paramsName = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
//记录入参
if (args != null && paramsName != null && args.length > 0 && paramsName.length > 0) {
for (int i = 0; i < paramsName.length; i++) {
reqStr.append(" ").append(paramsName[i]).append(" = ").append(args[i]).append(",");
}
reqStr.deleteCharAt(reqStr.length() - 1);
}
logger.error("错误日志【{}.{}】接口开始调用,入参:{}", className, methodName, reqStr);
// 将异常的堆栈信息转换为字符串
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
String stackTrace = sw.toString();
String phone = (String) request.getAttribute("phone");
sysLog.setClassName(className);
sysLog.setMethodName(methodName);
sysLog.setRequest(reqStr.toString());
sysLog.setResponse(respStr);
sysLog.setException(stackTrace);
sysLog.setPhone(phone);
//保存异常信息
logService.save(sysLog);
logger.warn("保存错误日志结束【{}.{}】", className, methodName);
} catch (Exception e) {
e.printStackTrace();
logger.info("保存日志异常:{}", e.getMessage());
}
}
}