aspect操作日志


aspect操作日志

00 导入依赖

        
        <dependency>
            <groupId>org.assertjgroupId>
            <artifactId>assertj-coreartifactId>
            <version>3.13.2version>
        dependency>

        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.9.5version>
        dependency>    

01 日志注解

package com.saiyou.annotation;
?
import com.saiyou.enums.BusinessType;
?
import java.lang.annotation.*;
?
/**
* 自定义操作日志注解
* @author lyn
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**
* 模块
*
*/
String title() default"";
?
/**
* 功能
*
*/
BusinessType businesstype () default BusinessType.OTHER;
?
/**
* 是否保存请求参数
*
*/
boolean isSaveRequestData() default true;
}
?

02 操作日志记录处理(aspect)

package com.saiyou.aspect;
?
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.saiyou.annotation.Log;
import com.saiyou.controller.interceptor.UserHolder;
import com.saiyou.entity.dto.LoginUserInfoDTO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
?
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
?
/**
* 操作日志记录处理
* 描述: aop,aspect
*
* @author lyn
* @date 2022/3/4 14:42
*/
@Aspect
@Component
public class LogAspect {
  /**
   * 配置织入点
   */
  @Pointcut("@annotation(com.saiyou.annotation.Log)")
  public void logPointcut() {
?
  }
?
  /**
   * 处理完请求后执行
   *
   * @param joinPoint 切点
   * @param jsonResult 返回参数
   */
  @AfterReturning(pointcut = "logPointcut()", returning = "jsonResult")
  public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
     handleLog(joinPoint, null, jsonResult);
  }
?
?
  @AfterThrowing(pointcut = "logPointcut()", throwing = "e")
  public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
     handleLog(joinPoint, e, null);
  }
?
  private void handleLog(JoinPoint joinPoint, Exception e, Object jsonResult) {
     Log logAnnotation = getAnnotationLog(joinPoint);
     if (Objects.isNull(logAnnotation)) {
        return;
    }
     //从ThreadLocal中获取当前用户
     LoginUserInfoDTO loginUser = UserHolder.get();
     //记录操作人的信息(略)
     //记录返回参数jsonResult
     //获取日志注解中的信息
     String title = logAnnotation.title();
     //序号
     int ordinal = logAnnotation.businesstype().ordinal();
     if (Objects.isNull(e)) {
        //记录错误信息
    }
     if (logAnnotation.isSaveRequestData()) {
        //获取请求参数
        String paramsStr = getRequestParam(joinPoint);
        System.out.println(paramsStr);
    }
     //保存日志(异步or中间件)
  }
?
  /**
   * 是否存在注解,如果存在就返回
   *
   * @param joinPoint
   * @return
   */
  private Log getAnnotationLog(JoinPoint joinPoint) {
     //签名
     Signature signature = joinPoint.getSignature();
     //强转成方法签名
     MethodSignature methodSignature = (MethodSignature) signature;
     Method method = methodSignature.getMethod();
     if (Objects.nonNull(method)) {
        return method.getAnnotation(Log.class);
    }
     return null;
  }
?
  /**
   * 获取请求的参数
   *
   * @param joinPoint
   */
  private String getRequestParam(JoinPoint joinPoint) {
     //如果方法是put或者是post 则按如下方式获取请求参数字符串
     Object[] params = joinPoint.getArgs();
     if (params != null) {
        return argsArrayToString(params);
    }
     return null;
     
  }
?
  /**
   * 参数拼装
   */
  private String argsArrayToString(Object[] paramsArray) {
?
     StringBuilder sbr = new StringBuilder("");
     if (paramsArray != null && paramsArray.length > 0) {
        for (int i = 0; i < paramsArray.length; i++) {
           if (ObjectUtil.isNotNull(paramsArray[i]) && !isFilterObject(paramsArray[i])) {
              //javaBean、列表数组转换为json字符串
              String jsonObj = objToJson(paramsArray[i]);
              sbr.append(jsonObj).append(" ");
          }
        }
    }
     return sbr.toString().trim();
  }
?
  /**
   * 判断是否需要过滤的对象。(MultipartFile是过滤对象)
   *
   * @param o 对象信息。
   * @return 如果是需要过滤的对象,则返回true;否则返回false。
   */
  @SuppressWarnings("rawtypes")
  public boolean isFilterObject(final Object o) {
     Class<?> clazz = o.getClass();
     if (clazz.isArray()) {
        return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
    } else if (Collection.class.isAssignableFrom(clazz)) {
        Collection collection = (Collection) o;
        for (Iterator iter = collection.iterator(); iter.hasNext(); ) {
           return iter.next() instanceof MultipartFile;
        }
    } else if (Map.class.isAssignableFrom(clazz)) {
        Map map = (Map) o;
        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {
           Map.Entry entry = (Map.Entry) iter.next();
           return entry.getValue() instanceof MultipartFile;
        }
    }
     return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
           || o instanceof BindingResult;
  }
?
  private final static ObjectMapper objectMapper = new ObjectMapper();
?
  /**
   * javaBean、列表数组转换为json字符串
   */
  public static String objToJson(Object obj) {
     try {
        return objectMapper.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
     return null;
  }
}