|
|
@@ -3,6 +3,7 @@ package cn.tr.plugin.operatelog.config;
|
|
|
import cn.hutool.core.date.DateUnit;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.ArrayUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.tr.core.pojo.CommonResult;
|
|
|
import cn.tr.core.strategy.ExceptionStrategy;
|
|
|
@@ -12,6 +13,7 @@ import cn.tr.core.utils.JsonUtils;
|
|
|
import cn.tr.core.utils.ServletUtils;
|
|
|
import cn.tr.plugin.operatelog.annotation.OperateLog;
|
|
|
import cn.tr.plugin.operatelog.bo.OperateLogBO;
|
|
|
+import cn.tr.plugin.operatelog.enums.LoginType;
|
|
|
import cn.tr.plugin.operatelog.strategy.OperateStrategy;
|
|
|
import cn.tr.plugin.web.context.RequestContextHolder;
|
|
|
import io.swagger.annotations.ApiOperation;
|
|
|
@@ -20,14 +22,22 @@ import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
import org.aspectj.lang.annotation.Around;
|
|
|
import org.aspectj.lang.annotation.Aspect;
|
|
|
import org.aspectj.lang.reflect.MethodSignature;
|
|
|
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
|
|
import org.springframework.core.annotation.AnnotationUtils;
|
|
|
+import org.springframework.expression.ExpressionParser;
|
|
|
+import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
|
+import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
|
import org.springframework.validation.BindingResult;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import javax.security.auth.login.LoginContext;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.lang.annotation.Annotation;
|
|
|
import java.lang.reflect.Array;
|
|
|
+import java.lang.reflect.Method;
|
|
|
import java.util.*;
|
|
|
import java.util.function.Predicate;
|
|
|
import java.util.stream.IntStream;
|
|
|
@@ -45,22 +55,24 @@ public class OperateLogAspect {
|
|
|
// 兼容处理,只添加 @OperateLog 注解的情况
|
|
|
public Object around(ProceedingJoinPoint joinPoint,
|
|
|
OperateLog operateLog) throws Throwable {
|
|
|
- return around0(joinPoint, operateLog, null);
|
|
|
+ return around0(joinPoint, operateLog);
|
|
|
}
|
|
|
|
|
|
private Object around0(ProceedingJoinPoint joinPoint,
|
|
|
- OperateLog operateLog,
|
|
|
- ApiOperation apiOperation) throws Throwable {
|
|
|
+ OperateLog operateLog) throws Throwable {
|
|
|
// 记录开始时间
|
|
|
Date startTime = new Date();
|
|
|
try {
|
|
|
// 执行原有方法
|
|
|
Object result = joinPoint.proceed();
|
|
|
// 记录正常执行时的操作日志
|
|
|
- this.log(joinPoint, operateLog, apiOperation, startTime, result, null);
|
|
|
+ this.log(joinPoint, operateLog,startTime, result, null);
|
|
|
return result;
|
|
|
} catch (Throwable exception) {
|
|
|
- this.log(joinPoint, operateLog, apiOperation, startTime, null, exception);
|
|
|
+ if(ObjectUtil.equals(operateLog.loginType(),LoginType.oper)){
|
|
|
+ //登录失败和登出失败不做记录
|
|
|
+ this.log(joinPoint, operateLog, startTime, null, exception);
|
|
|
+ }
|
|
|
throw exception;
|
|
|
}
|
|
|
}
|
|
|
@@ -68,24 +80,24 @@ public class OperateLogAspect {
|
|
|
|
|
|
private void log(ProceedingJoinPoint joinPoint,
|
|
|
OperateLog operateLog,
|
|
|
- ApiOperation apiOperation,
|
|
|
Date startTime, Object result, Throwable exception) {
|
|
|
try {
|
|
|
// 判断不记录的情况
|
|
|
- if (!isLogEnable(joinPoint, operateLog)) {
|
|
|
+ if (!isLogEnable(operateLog)) {
|
|
|
return;
|
|
|
}
|
|
|
// 真正记录操作日志
|
|
|
- this.log0(joinPoint, operateLog, apiOperation, startTime, result, exception);
|
|
|
+ this.log0(joinPoint, operateLog,startTime, result, exception);
|
|
|
} catch (Throwable ex) {
|
|
|
- log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) operateLog({}) apiOperation({}) result({}) exception({}) ]",
|
|
|
- joinPoint, operateLog, apiOperation, result, exception, ex);
|
|
|
+ log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) operateLog({}) result({}) exception({}) ]",
|
|
|
+ joinPoint, operateLog, result, exception, ex);
|
|
|
throw ex;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, Date startTime, Object result, Throwable exception) {
|
|
|
+ private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog ,Date startTime, Object result, Throwable exception) {
|
|
|
OperateLogBO log = new OperateLogBO();
|
|
|
+ ApiOperation apiOperation = getMethodAnnotation(joinPoint, ApiOperation.class);
|
|
|
// 补全通用字段
|
|
|
log.setOpTime(startTime);
|
|
|
// 补充用户信息
|
|
|
@@ -96,7 +108,6 @@ public class OperateLogAspect {
|
|
|
fillRequestFields(log);
|
|
|
// 补全方法信息
|
|
|
fillMethodFields(log, joinPoint, operateLog, startTime, result, exception);
|
|
|
-
|
|
|
// 异步记录日志
|
|
|
OperateStrategy.tr.saveLog(log);
|
|
|
}
|
|
|
@@ -107,25 +118,21 @@ public class OperateLogAspect {
|
|
|
OperateLog operateLog,
|
|
|
Date startTime, Object result, Throwable exception) {
|
|
|
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
|
|
-
|
|
|
operateLogObj.setJavaClass(methodSignature.getMethod().getDeclaringClass().getCanonicalName());
|
|
|
operateLogObj.setJavaMethod(methodSignature.toString());
|
|
|
-
|
|
|
-
|
|
|
operateLogObj.setDuration((int) (DateUtil.between(startTime,DateUtil.date(),DateUnit.MS)));
|
|
|
// 处理响应结果
|
|
|
if (result != null) {
|
|
|
- operateLogObj.setResponseType(true);
|
|
|
- if (operateLog == null || operateLog.logArgs()) {
|
|
|
+ operateLogObj.setType(operateLog.loginType().name());
|
|
|
+ if (operateLog.logResultData()) {
|
|
|
operateLogObj.setResultJson(obtainMethodArgs(joinPoint));
|
|
|
}
|
|
|
}
|
|
|
// (异常)处理 resultCode 和 resultMsg 字段
|
|
|
if (exception != null) {
|
|
|
- operateLogObj.setResponseType(false);
|
|
|
- if (operateLog == null || operateLog.logArgs()) {
|
|
|
- operateLogObj.setResultJson(obtainResultData( ExceptionStrategy.tr.exceptionHandle(ServletUtils.getRequest(),exception)));
|
|
|
- }
|
|
|
+ operateLogObj.setType(LoginType.exception.name());
|
|
|
+ operateLogObj.setResultJson(obtainResultData( ExceptionStrategy.tr.exceptionHandle(ServletUtils.getRequest(),exception)));
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -205,21 +212,18 @@ public class OperateLogAspect {
|
|
|
if (operateLog != null) {
|
|
|
operateLogObj.setOpName(operateLog.name());
|
|
|
}
|
|
|
- if (StrUtil.isEmpty(operateLogObj.getOpName()) && apiOperation != null) {
|
|
|
+ if (StrUtil.isAllBlank(operateLogObj.getOpName()) && apiOperation != null) {
|
|
|
operateLogObj.setOpName(apiOperation.value());
|
|
|
}
|
|
|
// content
|
|
|
operateLogObj.setRequestArgs(RequestContextHolder.getRequestBody());
|
|
|
}
|
|
|
|
|
|
- private static boolean isLogEnable(ProceedingJoinPoint joinPoint,
|
|
|
- OperateLog operateLog) {
|
|
|
- // 有 @OperateLog 注解的情况下
|
|
|
- if (operateLog != null) {
|
|
|
- return operateLog.enable();
|
|
|
+ private static boolean isLogEnable(OperateLog operateLog) {
|
|
|
+ if(operateLog==null){
|
|
|
+ return false;
|
|
|
}
|
|
|
- // 没有 @ApiOperation 注解的情况下,只记录 GET、POST、PUT、DELETE 的情况
|
|
|
- return obtainFirstLogRequestMethod(obtainRequestMethod(joinPoint)) != null;
|
|
|
+ return operateLog.enable();
|
|
|
}
|
|
|
|
|
|
private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) {
|
|
|
@@ -241,4 +245,28 @@ public class OperateLogAspect {
|
|
|
((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class);
|
|
|
return requestMapping != null ? requestMapping.method() : new RequestMethod[]{};
|
|
|
}
|
|
|
+
|
|
|
+ private static <T extends Annotation> T getMethodAnnotation(ProceedingJoinPoint joinPoint, Class<T> annotationClass) {
|
|
|
+ return ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(annotationClass);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析
|
|
|
+ * @param expressionString el表达式
|
|
|
+ * @param method 拦截方法
|
|
|
+ * @param args 拦截参数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private String parseExpression(String expressionString, Method method, Object[] args) {
|
|
|
+ //获取被拦截方法参数名列表
|
|
|
+ LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
|
|
|
+ String[] paramNameArr = discoverer.getParameterNames(method);
|
|
|
+ //SPEL解析
|
|
|
+ ExpressionParser parser = new SpelExpressionParser();
|
|
|
+ StandardEvaluationContext context = new StandardEvaluationContext();
|
|
|
+ for (int i = 0; i < paramNameArr.length; i++) {
|
|
|
+ context.setVariable(paramNameArr[i], args[i]);
|
|
|
+ }
|
|
|
+ return parser.parseExpression(expressionString).getValue(context, String.class);
|
|
|
+ }
|
|
|
}
|