• 通过切面日志实现业务数据历史变更


    1. 通过切面环绕通知获取方法访问前,后的参数来实现日志及业务数据变化
    2. 前端实现数据列表查询
    3. 业务数据对比,每一行数据根据当前的业务主键查询上一条业务数据,
        通过两次的传输参数进行对比实现直观的数据变化
    4. 此种方法缺点:
        每次对比只能对比已有参数的变化,没有传输的无法对比,(可以通过找权限变化的数据来实现全部对比)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    元数据注解

    /**
     * 操作日志注解
    *
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface LogOperation {
        String value() default "";
    
        /**
         * 传参中已有业务主键
         * @return
         */
        String primaryKey() default "id";
    
        /**
         * 返回参数中已有业务主键,JSON字符串中多层嵌套,自定义 如 data.id
         * @return
         */
        String resultPrimaryKey() default "data";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    切面实现类

    /**
     * 操作日志,切面处理类
     */
    @Aspect
    @Component
    public class LogOperationAspect {
        @Autowired
        private SysLogOperationService sysLogOperationService;
    
        @Pointcut("@annotation(com.mv.common.annotation.LogOperation)")
        public void logPointCut() {
        }
    
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            long beginTime = System.currentTimeMillis();
            Object result = null;
            try {
                //执行方法结果
                result = point.proceed();
                //执行时长(毫秒)
                long time = System.currentTimeMillis() - beginTime;
                //保存日志
                saveLog(point, time, OperationStatusEnum.SUCCESS.value(), result);
                return result;
            } catch (Exception e) {
                //执行时长(毫秒)
                long time = System.currentTimeMillis() - beginTime;
                //保存日志
                saveLog(point, time, OperationStatusEnum.FAIL.value(), result);
                throw e;
            }
        }
    
        private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status, Object result) throws Exception {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
            LogOperation annotation = method.getAnnotation(LogOperation.class);
            SysLogOperationEntity log = new SysLogOperationEntity();
            String primaryKey = null;
            String resultPrimaryKey = null;
            if (annotation != null) {
                //注解上的描述
                log.setOperation(annotation.value());
                primaryKey = annotation.primaryKey();
                resultPrimaryKey = annotation.resultPrimaryKey();
            }
            //登录用户信息
            UserDetail user = SecurityUser.getUser();
            if (user != null) {
                log.setCreatorName(user.getUsername());
            }
            log.setStatus(status);
            log.setRequestTime((int) time);
            //请求相关信息
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            if (null == request) {
                return;
            }
            log.setIp(IpUtils.getIpAddr(request));
            log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
            log.setRequestUri(request.getRequestURI());
            log.setRequestMethod(request.getMethod());
            //请求参数
            Object[] args = joinPoint.getArgs();
            try {
                String params = JSON.toJSONString(args[0]);
                log.setRequestParams(params);
                // 业务主键获取
                String tableKey = getTabkeKey(params, result, primaryKey, resultPrimaryKey);
                log.setBusinessId(tableKey);
                //判断参数 是否等于uri最后一个参数一样
                String[] paths = log.getRequestUri().split("/");
                if (paths[paths.length - 1].equals(params)) {
                    log.setRequestUri(log.getRequestUri().replaceAll(params, ""));
                }
            } catch (Exception e) {
            }
            //保存到DB
            sysLogOperationService.save(log);
        }
    
        private String getTabkeKey(String params, Object result, String primaryKey, String resultPrimaryKey) {
            try {
                JSONObject json = JSONObject.parseObject(params);
                String tableKey = null == json.get(primaryKey) ? null : json.get(primaryKey).toString();
                if (StringUtils.isEmpty(tableKey)) {
                    json = JSONObject.parseObject(JSON.toJSONString(result));
                    if (resultPrimaryKey.contains(":")) {
                        String[] keys = resultPrimaryKey.split(":");
                        for (int i = 0; i < keys.length; i++) {
                            if (i == keys.length - 1) {
                                tableKey = null == json.get(keys[i]) ? null : json.get(keys[i]).toString();
                            } else {
                                json = json.getJSONObject(keys[i]);
                            }
                        }
                    } else {
                        tableKey = null == json.get(resultPrimaryKey) ? null : json.get(resultPrimaryKey).toString();
                    }
                }
                return tableKey;
            } catch (Exception e) {
                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

    实体类

    /**
     * 操作日志
    *
     * @since 1.0.0
     */
    @Data
    @EqualsAndHashCode(callSuper=false)
    @TableName("sys_log")
    public class SysLogOperationEntity extends BaseEntity {
    	private static final long serialVersionUID = 1L;
    /**
    	 * 用户操作
    	 */
    	private String operation;
    	/**
    	 * 请求URI
    	 */
    	private String requestUri;
    	/**
    	 * 请求方式
    	 */
    	private String requestMethod;
    	/**
    	 * 请求参数
    	 */
    	private String requestParams;
    	/**
    	 * 业务主键
    	 */
    	private String businessId;
    	/**
    	 * 请求时长(毫秒)
    	 */
    	private Integer requestTime;
    	/**
    	 * 用户代理
    	 */
    	private String userAgent;
    	/**
    	 * 操作IP
    	 */
    	private String ip;
    	/**
    	 * 状态  0:失败   1:成功
    	 */
    	private Integer status;
    	/**
    	 * 用户名
    	 */
    	private String creatorName;
    }
    
    • 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
  • 相关阅读:
    学习笔记:卸载nav2 navigation2导航
    virtio-wayland
    java类加载和双亲委派模型浅说
    FPGA 20个例程篇:13.千兆网口实现ARP通信协议(上)
    leetcode-数组
    TS类型: never 和 unknown
    Android数据库处理重复插入Insert数据的问题
    思科C9300交换机Bundle模式转换为Install模式
    记录近期修复Dataguard的过程
    C++核心编程 day09 类型转换、异常、输入输出流
  • 原文地址:https://blog.csdn.net/u011128560/article/details/133742396