SpringAop日志记录

spring日志记录(使用切面方式记录)

执行流程图

SpringAop日志记录_第1张图片

1. 创建pojo类

@Data
@Table(name = "tb_operate_record")
public class OperateRecord {
    @Id
    private String id;
    //记录请求时间
    @Column(name = "record_time")
    private Date recordTime;
    //操作者
    private String username;
    //请求IP
    @Column(name = "request_ip")
    private String requestIp;
    //操作类型, true操作记录 false异常记录
    private Boolean type;
    //请求的方法
    @Column(name = "request_method")
    private String requestMethod;
    //自定义注解中的name
    @Column(name = "request_annotation_name")
    private String requestAnnotationName;
    //异常描述
    @Column(name = "exception_msg")
    private String exceptionMsg;
}
/**
 * 系统日志事件
 */
public class OperateRecordEvent extends ApplicationEvent {
    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public OperateRecordEvent(Object source) {
        super(source);
    }
}

2.创建自定义注解

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface LogRecord {
    String value() default "";
}

3.创建监听器

/**
 * 注解形式的监听,异步监听日志事件
 */
@Component @Slf4j
public class OperateRecordListener {
    @Autowired
    private OperateRecordService operateRecordService;
    @Async @Order @EventListener(OperateRecordEvent.class)
    public void saveOperateRecord(OperateRecordEvent event) {
        OperateRecord operateRecord = (OperateRecord) event.getSource();
        //保存日志
        operateRecordService.save(operateRecord);
    }
}

4.创建切面类


/**
 * 操作日志切面
 * 且体面注解得到请求数据 --> 发布监听事件 --> 异步监听日志入库
 */
@Component @Aspect@Slf4j
public class OperateAspect {
    // 创建OperateRecord对象
    private OperateRecord operateRecord = new OperateRecord();
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private RsaKeyProperties properties;
    /**
     * 定义controller切入点拦截规则,拦截LogRecord注解的方法
     */
    @Pointcut("@annotation(com.mayday.common.api.LogRecord)")
    public void operateAspect() {

    }
    /**
     * 拦截控制层的操作日志
     *
     * @param joinPoint
     */
    @Before(value = "operateAspect()")
    public void recordLog(JoinPoint joinPoint) throws Exception {
        //获取request对象
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        operateRecord.setId(String.valueOf(new IdWorker().nextId()));
        operateRecord.setRecordTime(new Date());
        operateRecord.setRequestIp(request.getRemoteHost());
        String username = this.getUsernameByRequest(request);
        operateRecord.setUsername(StringUtils.isNotEmpty(username) ? username : "anonymous");
        operateRecord.setRequestMethod(joinPoint.getTarget().getClass().getSimpleName() + "." + joinPoint.getSignature().getName());
        operateRecord.setRequestAnnotationName(this.getControllerMethodDescription(joinPoint));
    }

    /**
     * 返回通知
     *
     * @param ret
     */
    @AfterReturning(returning = "ret", pointcut = "operateAspect()")
    public void doAfterReturning(Object ret) {
        //处理完请求,返回内容
        Result result = Convert.convert(Result.class, ret);
        if (result.getFlag()) {
            //正常返回
            operateRecord.setType(true);
        } else {
            operateRecord.setType(false);
            String resultMsg = result.getMessage();
            if ((StringUtils.length(resultMsg) > 10)) {
                operateRecord.setExceptionMsg(resultMsg.substring(0, 10));
            } else {
                operateRecord.setExceptionMsg(resultMsg);
            }
        }
        //发布事件
        applicationContext.publishEvent(new OperateRecordEvent(operateRecord));
    }

    /**
     * 异常通知
     *
     * @param e
     */
    @AfterThrowing(pointcut = "operateAspect()", throwing = "e")
    public void doAfterThrowable(Throwable e) {
        //异常
        operateRecord.setType(false);
        operateRecord.setExceptionMsg(e.getMessage());
        //发布事件
        applicationContext.publishEvent(new OperateRecordEvent(operateRecord));
    }


    /**
     * 通过request对象获取用户名
     *
     * @param request
     * @return
     */
    private String getUsernameByRequest(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
        if (StringUtils.isNotEmpty(header) && header.startsWith("Bearer ")) {
            String token = header.replace("Bearer ", "");
            Payload payload = JwtUtils.genInfoFromToken(token, properties.getPublicKey(), User.class);
            return payload.getUserInfo().getUsername();
        }
        return null;
    }


    /**
     * 获取方法上对应注解的value
     *
     * @param joinPoint
     * @return
     * @throws Exception
     */
    private String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
        //获取连接点目标类型
        String targetName = joinPoint.getTarget().getClass().getName();
        //获取连接点签名的方法名
        String methodName = joinPoint.getSignature().getName();
        //获取连接点参数
        Object[] args = joinPoint.getArgs();
        //根据连接点类的名字获取指定类
        Class targetClass = Class.forName(targetName);
        //获取类里面的方法
        Method[] methods = targetClass.getMethods();
        String value = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] cls = method.getParameterTypes();
                if (cls.length == args.length) {
                    value = method.getAnnotation(LogRecord.class).value();
                    break;
                }
            }
        }
        return value;

    }
}

5.在相应的类上加上注解

SpringAop日志记录_第2张图片

你可能感兴趣的:(spring,boot,java,aop,spring,spring,boot)