springAop之 记录登入日志

注解类

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditLog {
    boolean skip() default false;
}

Aop运用

/**
 * Aspect for logging execution of service and repository Spring components.
 * <p>
 * By default, it only runs with the "dev" profile.
 */
@Aspect
public class LoggingAspect {

  private final Logger log = LoggerFactory.getLogger(LoggingAspect.class);

  @Inject
  private LoggingService loggingService;

  private final Environment env;
  @Value("${app.auditLogFlag.printGet}")
  private boolean logFlag;

  ObjectMapper mapper = new ObjectMapper();

  public LoggingAspect(Environment env) {
    this.env = env;
  }

  /**
   * Pointcut that matches all repositories, services and Web REST endpoints.
   */
  @Pointcut("within(com.qingxing.ManagerComplex.api.web.*.*Resource)")
  public void loggingPointcut() {
    // Method is empty as this is just a Pointcut, the implementations are in the advices.
  }

  /**
   * Advice that logs methods throwing exceptions.
   */
  @AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
  public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
    if (env.acceptsProfiles(Constants.SPRING_PROFILE_DEVELOPMENT)) {
      log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'",
        joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
        e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e);
    } else {
      log.error("Exception in {}.{}() with cause = {}",
        joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
        e.getCause() != null ? e.getCause() : "NULL");
    }
  }

  /**
   * Advice that logs when a method is entered and exited.
   */
  @Around("loggingPointcut()")
  public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

    ServletRequestAttributes attributes =
      (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    // 获取ip
    String ip = LogUtil.getIpAddress(request);

    // 获取请求头与操作路径

    String path = request.getHeader("Page-Name");
    if (!StringUtils.isBlank(path)) {
      try {
        path = URLDecoder.decode(path, "UTF-8");
      } catch (UnsupportedEncodingException e1) {
        e1.printStackTrace();
        log.error("解码错误" + e1.getMessage());
      }
    }
    // 获取当前用户名
    String username = UserUtil.getUser().getUsername();
    String area = LogUtil.sqlArea(UserUtil.getUser().getArea());

    // 通过反射获取方法
    String classType = joinPoint.getTarget().getClass().getName();
    Class<?> clazz = Class.forName(classType);
    String clazzName = clazz.getName();
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method targetMethod = methodSignature.getMethod();

    Method realMethod = joinPoint.getTarget().getClass()
      .getDeclaredMethod(joinPoint.getSignature().getName(), targetMethod.getParameterTypes());

    String methodName = joinPoint.getSignature().getName(); // 获取方法名称
    Object[] args = joinPoint.getArgs();
    Map<String, Object> nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName, args); // 获取参数名称和值

    try {

      if (!realMethod.isAnnotationPresent(ApiOperation.class)) {
        return 1;
      }
      // 将map转换为json
      String json = mapper.writeValueAsString(nameAndArgs);

      // 获取操作内容
      ApiOperation apiOperation = realMethod.getAnnotation(ApiOperation.class);
      String apiOperationString = apiOperation.value();
      boolean isGet = realMethod.isAnnotationPresent(GetMapping.class);
      // 判断是否存在 AuditLog 注解
      if (realMethod.isAnnotationPresent(AuditLog.class)) {
        AuditLog auditLog = realMethod.getAnnotation(AuditLog.class);
        boolean skipFlag = auditLog.skip();
        joinDatabase(skipFlag, area, username, ip, path, apiOperationString, json);
      } else {
        // 判断是否 get 请求,以及是否强制打印
        joinDatabase(!isGet || !logFlag, area, username, ip, path, apiOperationString, json);
      }
    } catch (Exception e) {
      log.error(e.getMessage());
    }
    return doNext(joinPoint);
  }

  private Object doNext(ProceedingJoinPoint joinPoint) throws Throwable {
    try {
      Object result = joinPoint.proceed();
      if (log.isDebugEnabled()) {
        log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
          joinPoint.getSignature().getName(), result);
      }
      return result;
    } catch (IllegalArgumentException e) {
      log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
        joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());

      throw e;
    }
  }

  /**
   * 记录插入数据库
   */
  private void joinDatabase(boolean flag, String area, String username, String ip, String path,
                            String apiOperationString, String json) {
    if (flag) {
      loggingService.addLogging(area, username, ip, path, apiOperationString, json);
      log.debug("插入数据库成功  " + " 区域:" + area + " 用户名:" + username + " ip地址: " + ip + " 操作路径: " + path + " ,操作:"
        + apiOperationString + ", 参数为:" + json + ", 操作时间为:" + new Date());
    } else {
      log.debug(" 区域:" + area + " 用户名:" + username + " ip地址: " + ip + " 操作路径: " + path + " ,操作:" + apiOperationString
        + ", 参数为:" + json + ", 操作时间为:" + new Date());
    }
  }

  //全部参数转换为map
  private Map<String, Object> getFieldsName(Class cls, String clazzName, String methodName,
                                            Object[] args) throws NotFoundException {
    if (args == null || args.length <= 0) return null;
    Map<String, Object> map = new HashMap<>();
    ClassPool pool = ClassPool.getDefault();
    // ClassClassPath classPath = new ClassClassPath(this.getClass());
    ClassClassPath classPath = new ClassClassPath(cls);
    pool.insertClassPath(classPath);

    CtClass cc = pool.get(clazzName);
    CtMethod cm = cc.getDeclaredMethod(methodName);
    org.apache.ibatis.javassist.bytecode.MethodInfo methodInfo = cm.getMethodInfo();
    CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
    LocalVariableAttribute attr =
      (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
    if (attr != null) {
      // String[] paramNames = new String[cm.getParameterTypes().length];
      int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
      for (int i = 0; i < cm.getParameterTypes().length; i++) {
        if (args[i] == null) {
          map.put(attr.variableName(i + pos), "");
          continue;
        }

        String argsStr = args[i].toString();

        try {
          if (argsStr.getBytes("UTF-8").length < 3000) {
            map.put(attr.variableName(i + pos), args[i]);// paramNames即参数名
          } else {
            String[] msg = StringCutUtil.cutByteByUTF8(args[i].toString(), 512);
            map.put(attr.variableName(i + pos), msg[0]);
            log.debug("超级长的参数{},时间是{}", args[i], new Date());

          }
        } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
        }
      }
    }
    // Map<>
    return map;
  }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值