欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring AOP注解方式实现日志管理

程序员文章站 2022-04-25 16:45:22
...

前言:使用注解方式实现日志管理,可以使我们的程序变的清晰、简单,不和很多业务代码混在一起。

实现思路大致分为四点

  • 设计日志表和日志类,编写日志Dao和Service以及实现
  • 自定义注解,注解中加入几个属性,属性可以标识操作的类型(方法是做什么的)
  • 编写切面,切点表达式使用上面的注解直接定位到使用注解的方法,
  • 编写通知,通过定位到方法,获取上面的注解以及注解的属性,然后从session中直接获取或者从数据库获取当前登录用户的信息,最后根据业务处理一些日志信息之后调用日志Service存储日志

设计日志表和日志类此步骤将省略可以根据自己的实际情况设计

自定义注解

BussLog

package com.sl.annotation;

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

/**
 * @author shuliangzhao
 * @Title: BussLog
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/14 20:06
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface BussLog {
    /**
     * 业务的名称
     */
    String value() default "";
    

    /**
     * 是否将当前日志记录到数据库中
     */
    boolean save() default true;
}

BussLogAspect

package com.sl.aop;

import com.alibaba.fastjson.JSON;
import com.sl.annotation.BussLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author shuliangzhao
 * @Title: BussLogAspect
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/14 20:08
 */
@Aspect
@Component
@EnableAspectJAutoProxy
public class BussLogAspect {

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

    @Pointcut(value = "@annotation(com.sl.annotation.BussLog)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object writeLog(ProceedingJoinPoint point) throws Throwable {

        //先执行业务
        Object result = point.proceed();

        try {
            handle(point);
        } catch (Exception e) {
            log.error("日志记录出错!", e);
        }

        return result;
    }

    private void handle(ProceedingJoinPoint point) throws Exception {
        Method currentMethod = getMethod(point);
        //获取操作名称
        BussLog annotation = currentMethod.getAnnotation(BussLog.class);
        boolean save = annotation.save();
        String bussinessName = parseParams(point.getArgs(), annotation.value());

        log.info("{} | {} - {} {} - {}", bussinessName);
        if (!save) {
            return;
        }

    }

    private Method getMethod(JoinPoint point) throws NoSuchMethodException {
        Signature sig = point.getSignature();
        MethodSignature msig = (MethodSignature) sig;
        Object target = point.getTarget();
        return target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
    }
    public String parseParams(Object[] params, String bussinessName) {
        if (bussinessName.contains("{") && bussinessName.contains("}")) {
            List<String> result = match(bussinessName, "(?<=\\{)(\\d+)");
            for (String s : result) {
                int index = Integer.parseInt(s);
                bussinessName = bussinessName.replaceAll("\\{" + index + "}", JSON.toJSONString(params[index - 1]));
            }
        }
        return bussinessName;
    }

    private static List<String> match(String str, String regex) {
        if (null == str) {
            return null;
        }
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        List<String> list = new LinkedList<>();
        while (matcher.find()) {
            list.add(matcher.group());
        }
        return list;
    }
}