aspect操作日志

aspect操作日志

00 导入依赖

        <!--aspect -->
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.13.2</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </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;
   }
}
posted @ 2022-03-04 17:59  进击的小蔡鸟  阅读(176)  评论(0编辑  收藏  举报