aop记录日志到db

132 阅读1分钟

前言

业务开发中,某些业务需要记录用户操作前后的日志,做一些log操作证据。

实现

  • 在业务代码前后加save log 操作到 db
  • 使用aop 不改变业务代码的情况下记录Log

aop记录日志到db

  • 业务中全部打印日志
  • 记录部分日志到db

部分日志需要记录到db

这里我们自定义Log注解
然后使用aop扫描次注解记录该日志操作

Log注解

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /**
     * 模块
     */
    String module() default "";

    /**
     * 描述
     */
    String description() default "";
}

aop操作

package com.ly.traffic.ground.cxy.config;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Aspect
@Component
public class LogAspect {

    private LoggerHelper log = LoggerHelper.getLoggerHelper(Constants.ModuleName.OPEN_API, LogAspect.class.getSimpleName());

    /**
     * 日志切入点
     */
    @Pointcut("@annotation(com.xxxxxxxx.Log)")
    public void logPointCut() {
    }

    private static final ThreadLocal<LogOperation> threadLocal = new ThreadLocal();
//某个查询bean service 
    @Autowired
    private XXXXXXService xxxxxService;

	//这里我们日志服务的url
    @Value("${buss.api.url}")
    private String URL;

    @Before("logPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Cookie[] cookies = request.getCookies();

        if (cookies.length == 0) {
            return;
        }
        String unionId = "";
        for (int i = 0; i < cookies.length; i++) {
            if ("unionId".equals(cookies[i].getName())) {
                unionId = cookies[i].getValue();
                break;
            }
        }
        if (StringUtils.isEmpty(unionId)) {
            return;
        }
        String paramter = AopUtil.getString(joinPoint);

        LogOperation logOperation = new LogOperation(unionId);
        logOperation.setDescription(paramter);
        threadLocal.set(logOperation);
    }


    @AfterReturning(returning = "ret", pointcut = "logPointCut()")
    public void doAfterReturning(Object ret) {

        Result result = (Result) ret;
        if (!ResultCode.OK.val().equals(result.getCode())) {
            threadLocal.remove();
            return;
        }
        try {
            LogOperation logOperation = threadLocal.get();
            //异步记录日志
            ExecutorUtil.executor.submit(() -> {
                logOperation.setOperateType("1");
                logOperation.setPlatform(2);

                StewardInfo stewardInfo = xxxxxService.findByUnionId(logOperation.getUnionId());
                if (stewardInfo == null) {
                    return;
                }
                logOperation.setVcode(stewardInfo.getVcode());
                logOperation.setAccount(stewardInfo.getMobile());
                logOperation.setDescription( " 时间: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtil.DATE_PATTERN_YYYY_MM_DD_HH_MM_SS)) + ", 修改后数据 : " + logOperation.getDescription());
                URL =  URL.replace("buspassopenapi","");
                //add log send http
                String json = JSON.toJSONString(logOperation);
                String post = HttpUtils.post(URL+"/log/api/xxxxxx/saveLog", json);
                log.infoLog("记录日志返回 : " + post + " send data : " + json + " url : " + URL);

            });
        } finally {
            threadLocal.remove();
        }

    }

    @AfterReturning(pointcut = "logPointCut()")
    public void doAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Method method = currentMethod(joinPoint, methodName);
        Log log = method.getAnnotation(Log.class);
        LogOperation logOperation = threadLocal.get();
        //异步记录Log
        String unionId = logOperation.getUnionId();
        if (StringUtils.isEmpty(unionId)) {
            return;
        }
        logOperation.setOperateModule(log.module()+":"+log.description());
    }


    @AfterThrowing(value = "logPointCut()", throwing = "throwable")
    public void doAfterThrowing(Throwable throwable) {
        // 保存异常日志记录
        log.infoLog(throwable.getMessage());
        threadLocal.remove();


    }

    /**
     * 获取当前执行的方法
     *
     * @param joinPoint  连接点
     * @param methodName 方法名称
     * @return 方法
     */
    private Method currentMethod(JoinPoint joinPoint, String methodName) {
        /**
         * 获取目标类的所有方法,找到当前要执行的方法
         */
        Method[] methods = joinPoint.getTarget().getClass().getMethods();
        Method resultMethod = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                resultMethod = method;
                break;
            }
        }
        return resultMethod;
    }

}