定义日志注解

import java.lang.annotation.*;

/**
 * @author wzw
 * @version 1.0
 * @Date 2023-2-17 17:31:19
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

    /**
     * 描述
     * @return
     */
    String desc();


    boolean isSaveLog() default true;

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

定义切面

定义切面,在使用了指定注解的方法执行前后,进行操作,这里是用来在使用了自定义注解的方法执行完,保存日志信息 UserBean是测试系统的用户实体,BusinessLogs 是测试系统的日志实体,直接删掉就可以了

import com.alibaba.fastjson.JSON;
import com.weeon.platform.common.bean.UserBean;
import com.weeon.platform.common.dao.BusinessLogsDao;
import com.weeon.platform.common.domain.BusinessLogs;
import com.weeon.platform.common.utils.HttpRequestUtils;
import com.weeon.platform.common.utils.PrimaryKeyUtils;
import com.weeon.platform.common.utils.WebUserUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
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.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author wzw
 * @version 1.0
 * @Date 2023-2-17 17:31:19
 */
@Aspect
@Component
public class LogPoint {

    @Resource
    private BusinessLogsDao businessLogsDao;

    //配置织入点
    @Pointcut("@annotation(com.weeon.platform.api.log.Log)")
    public void logPointCut() {

    }

    /**
     * 处理完请求后执行
     *
     * @param joinPoint  切点
     * @param jsonResult 返回的信息
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterRetuning(JoinPoint joinPoint, Object jsonResult) {
        Log annotationLog = getAnnotationLog(joinPoint);
        if(annotationLog.isSaveLog()){
            handleLog(joinPoint, null, jsonResult);
        }
    }

    /**
     * 处理完请求之后执行
     *
     * @param joinPoint  切点
     * @param e          异常信息
     * @param jsonResult 返回结果
     */
    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {

        UserBean userBean = WebUserUtils.getUser();

        Log controllerLog = getAnnotationLog(joinPoint);
        if (controllerLog == null) {
            return;
        }

        BusinessLogs sysLog = new BusinessLogs();
        sysLog.setId(PrimaryKeyUtils.getId());

        // 请求的地址
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) attributes;
        HttpServletRequest request = ((ServletRequestAttributes) attributes).getRequest();

        //请求参数
        Map<String, String[]> param = ((ServletRequestAttributes) attributes).getRequest().getParameterMap();
        String s = JSON.toJSONString(param);
        s=s.replaceAll("(\\[)|(\\])","");
        sysLog.setParvalue(s);
        sysLog.setUrl(HttpRequestUtils.getRequestUrl(request) + " " + request.getMethod());

        //操作用户信息
        sysLog.setUserid(userBean.getUserid());
        sysLog.setUsername(userBean.getUsername());
        sysLog.setZtid(userBean.getZtid());
        sysLog.setZtcode(userBean.getZtcode());
        sysLog.setZtname(userBean.getZtname());
        String ip = HttpRequestUtils.getIp(request);
        sysLog.setIp(ip);

        // 设置方法名称
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        sysLog.setClassname("类名:" + className + " 方法:" + methodName + "()");

        //日志描述
        sysLog.setDescription(controllerLog.desc());

        // 保存到数据库
        businessLogsDao.save(sysLog);

    }

    /**
     * 是否存在注解,如果存在就获取
     *
     * @param joinPoint 切点
     * @return 注解对象
     */
    private Log getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }


}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.

使用

@Log(desc = "访问了/testhandler/test1路径",isSaveLog = false)
    @RequestMapping("/testhandler/test1")
    public String test1(){


        return "123";
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

其它

获取调用者类名和方法名

String className = new Exception().getStackTrace()[1].getClassName(); //获取调用者的类名
        String methodName = new Exception().getStackTrace()[1].getMethodName(); //获取调用者的方法名
  • 1.
  • 2.

切点

  • 使用@annotation(annotation)作为切点表达式,表示拦截所有带有指定注解的方法。
@AfterReturning(pointcut = "@annotation(Log)")
public void doAfterReturning(JoinPoint joinPoint, Log log) {
    // 处理日志
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 使用@target(target)作为切点表达式,表示拦截所有指定类型的方法。
@AfterReturning(pointcut = "@target(Controller)")
public void doAfterReturning(JoinPoint joinPoint, Controller controller) {
    // 处理日志
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 使用@within(within)作为切点表达式,表示拦截所有指定类型的类的方法。
@AfterReturning(pointcut = "@within(Service)")
public void doAfterReturning(JoinPoint joinPoint, Service service) {
    // 处理日志
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 使用@args(args)作为切点表达式,表示拦截所有带有指定参数的方法。
@AfterReturning(pointcut = "@args(String)")
public void doAfterReturning(JoinPoint joinPoint, String arg) {
    // 处理日志
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 使用@annotation(annotation)和@target(target)、@within(within)、@args(args)组合使用,表示拦截所有带有指定注解、指定类型、指定类型的类的方法、带有指定参数的方法。
@AfterReturning(pointcut = "@annotation(Log) && @target(Controller) && @args(String)")
public void doAfterReturning(JoinPoint joinPoint, Log log, Controller controller, String arg) {
    // 处理日志
}
  • 1.
  • 2.
  • 3.
  • 4.