• Spring AOP +自定义注解 + Spel表达式 实现审计日志


    1-简介

    • 审计日记就是记录用户的操作记录
    • 基于AOP动态代理 实现自定义审计日志注解, 并支持Spel表达式解析

    2-实现

    2-1 日志存储实体类

    @Data
    @Builder
    @ToString
    public class AuditingLog {
    
        private String userId;  // 用户id
    
        private String userNickname; //用户昵称
    
        private String operationInfo; //操作信息
    
        private String interfaceName; // 调用的接口方法名
    
        private String applicationName; // 调用的服务名
    
        private LocalDateTime createTime; //操作时间
    }

    2-2 自定义审计日志注解

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    public @interface AuditLog {
        String logInfo(); //日志信息
    }

    2-3 日志注解的AOP的切面

    @Aspect
    @Component
    public class AuditLogAOP {
    
           @Value("${spring.application.name}")
        private String applicationName; //从配置文件获得服务名
    
        // spel表达式解析器
        private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
    
        // 参数名发现器
        private DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
    
        @Before(value = "@annotation(enableAuditLog) || @within(enableAuditLog)")
        public void getAutiLogInfo(JoinPoint joinPoint, AuditLog enableAuditLog){
    
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            if (enableAuditLog == null) {
                enableAuditLog = signature.getMethod().getAnnotation(AuditLog.class);
            }
    
            // 构建日志存储对象
            AuditingLog auditlog = AuditingLog.builder().applicationName(applicationName).createTime(LocalDateTime.now()).build();
    
            auditlog.setUserId(xxx);  // 从上下文获取当前操作的用户信息
            auditlog.setUserNickname(xx);
            
        // 设置操作的接口方法名        
        auditlog.setInterfaceName(signature.getDeclaringTypeName()+"."+signature.getName());
    
            // 获得日志注解上自定义的日志信息
            String logInfo = enableAuditLog.logInfo();
    
            // Spel表达式解析日志信息
            // 获得方法参数名数组
            String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod());
            if (parameterNames != null && parameterNames.length > 0){
                EvaluationContext context = new StandardEvaluationContext();
    
                //获取方法参数值
                Object[] args = joinPoint.getArgs();
                for (int i = 0; i < args.length; i++) {
                    context.setVariable(parameterNames[i],args[i]); // 替换spel里的变量值为实际值, 比如 #user -->  user对象
                }
    
                // 解析出实际的日志信息
                String opeationInfo = spelExpressionParser.parseExpression(logInfo).getValue(context).toString();
                auditlog.setOperationInfo(opeationInfo);
            }
    
            // 打印日志信息
            log.info(auditlog.toString());
    
            //TODO 这时可以将日志信息auditlog进行异步存储,比如写入到文件通过logstash增量的同步到Elasticsearch或者DB
    
        }
    }

    2-4 开启审计日志功能

    • 在分布式项目中一般会将日志抽离出来公共调用, 所以为了方便的注入审计日志功能,可以编写对应 Enable注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Import({AuditLogAOP.class}) // 注入AOP切面到容器
    public @interface EnableAuditLog {
    
    }

    3 使用

    3-1 开启审计日志功能

    • 在要使用审计日志功能的服务的入口类开启审计日志功能

    比如

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableAuditLog //开启审计日志
    public class UmsAdminApplication {
        public static void main(String[] args) {
            SpringApplication.run(UmsAdminApplication.class,args);
        }
    }

    3-2 在接口上使用

    比如:

        @AuditLog(logInfo = "'新增管理员:'+ #user.username")
        @PostMapping
        public String addUser(@RequestBody User user){
        
            return null;
        }
    转载:https://blog.csdn.net/weixin_41347419/article/details/107573038
  • 相关阅读:
    文本框测试用例
    用Apache生产csr申请证书
    apche配置后报错(Forbidden)没有权限
    Apache+Tomcat配置方法
    从程序员到项目经理:项目经理必须懂的一些章法
    linux 常见命令20200424
    Linux如何通过命令查看日志文件的某几行(中间极几行或最后几行)
    JPA和Hibernate的关系
    SpringBoot添加webapp目录
    @NotNull, @NotEmpty和@NotBlank之间的区别是什么?
  • 原文地址:https://www.cnblogs.com/duanxz/p/13725554.html
Copyright © 2020-2023  润新知