操作日志的内容记录及比对

原创 2018年04月17日 20:19:45

emmm,还是好久没更新博客了。老样子,懒,哈哈。

ok,回归正题,最近项目需要一个操作日志的内容比对,也就是哪些人在哪个业务的操作了哪些内容,操作前和操作后的内容比对及其他信息做为记录供人查阅。

最先想到的肯定是spring aop 拦截特定方法+自定义注解获取内容,操作前后的内容用json记录入库,比对内容可能就是jsonObject来进行比对。

因项目的特殊性和业务实体里可能会有循环引用等因素,在寻找了一些资料后决定

自定义注解 + MethodInterceptor + fastjson + jsondiffpatch + 消息队列

  • 自定义注解用来注明一些内容信息及要做记录的方法
  • 实现MethodInterceptor的invoke做方法前后及异常信息的拦截,request通过RequestContextListener的上下文来获取一些请求信息
  • fastjson做实体序列化和反序列化(因项目反序列化特殊性fastjson需要1.2.28+版本)
  • jsondiffpatch做内容比对 (jsondiffpatch的online demo
  • 消息队列做解析及入库解耦

先建立个自定义注解MyLog

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface MyLog {

    // 模块名
    String module() default "";

    // 操作内容
    String operate() default "";

    // 备注
    String remark() default "";

    //所属业务model class baseModel为业务基类
    Class<? extends BaseModel> clazz() default BaseModel.class;

}

实现methodInterceptor【也可以自己使用spring aop去设置拦截 请自行查询相关资料】

import com.alibaba.fastjson.JSON;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@Component
public class MyInterceptor implements MethodInterceptor {


    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {

        Method method = methodInvocation.getMethod();
//        if(method.isAnnotationPresent(MyLog.class)){
//            //未检测到注解则放行
//            return methodInvocation.proceed();
//        }

        MyLog myLog = method.getAnnotation(MyLog.class);
        if(myLog != null){
            //模块
            String module = myLog.module();
            //操作
            String operation = myLog.operation();
            //备注信息
            String remark = myLog.remark();
            //拦截的类
            Class<? extends BaseModel> clazz =  myLog.clazz();
        }

        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        if (request != null){
            //获取请求信息
            Map<String,String[]> parameterMap = request.getParameterMap();
            //请求头
            Map<String,String> headerMap = getHeader(request);

            //因项目的拦截方法请求request中会带id
            String id = request.getParameter("id");
            if(StringUtils.isNotBlank(id)){
//                BaseModel model = baseService.findById(id,clazz);
                //转json
//                 String json = JSON.toJSONString(model);
            }
        }

        //异常信息
        StringBuilder exceptionMessage = new StringBuilder();
        //方法返回值
        Object returnObj = null;
        //异常
        Exception exception = null;
        try {
            returnObj = methodInvocation.proceed();
        }catch (Exception e){
            exception = e;
            exceptionMessage.append(e.getClass().getName() + " : " + e.getMessage() + "\n");
            StackTraceElement[] trace = e.getStackTrace();
            for (StackTraceElement s : trace) {
                exceptionMessage.append("\tat " + s + "\r\n");
            }
        }

        //记录日志实体
        //log.setxxx(xxx);

        //发送消息队列
        //sendMessageService.send(logObject);


        if(exception != null){
            throw exception;
        }

        return returnObj;
    }


    /**
     * 获取header参数内容
     *
     * @return
     */
    private Map<String, String> getHeader(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>(0);
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }

}

配置spring的自动代理

 <!-- 通知器或切面 -->
    <bean id="operationLogAroundMethodPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice">
            <ref bean="operationLogAroundAdvice"/>
        </property>
        <property name="patterns">
            <list>
               <!-- 拦截全部方法 -->  
                <value>.*</value>
            </list>
        </property>
    </bean>

    <!-- 自动代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
               <!-- 哪些需要代理  -->
                <value>*Service</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>operationLogAroundMethodPointcutAdvisor</value>
            </list>
        </property>
    </bean>


使用方式就是在你的service接口上加入Mylog注解进行信息配置啦~

    @MyLog(module = "模块名", operate = "新增操作",clazz = XXXXX.class)
    String add(BaseModel model) throws Exception;

业务逻辑就是大概这样:

拦截要记录的接口,获取必要信息,从数据库获取操作前的数据转json存入库,同时记录该业务id和业务类,查看日志的时候从库中读取新的操作后的对象,转成操作后的json  2个json进行比对即可。


至于jsondiffpatch怎么使用官方比我讲的明白

https://www.npmjs.com/package/jsondiffpatch


参考:
https://github.com/alibaba/fastjson/wiki/PropertyNamingStrategy_cn
https://github.com/alibaba/fastjson/wiki/%E5%BE%AA%E7%8E%AF%E5%BC%95%E7%94%A8
https://github.com/alibaba/fastjson/wiki/incompatible_change_list
https://github.com/alibaba/fastjson/wiki/enable_autotype

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sd4000784/article/details/79978891

java spring 记录用户增删改操作日志

在数据库中建立操作记录(方式一)  建立操作记录(方法二)  使用LOG4J,通过配置LOG4J来获取业务日志(Apache Log4j)  用触发器生成SQL Server2000数据表的操作...
  • DD_lemon
  • DD_lemon
  • 2015-11-13 16:39:12
  • 16244

sqlite3操作记录

先附加数据库: attach database '/bak/ipguard.dat' as b_conf
  • u012846431
  • u012846431
  • 2014-10-28 14:17:00
  • 925

yii2记录admin操作日志

出于监控多用户操作后台的目的,往往需要把各个管理员操作了什么记录下来。这个功能用yii2来实现简直是太简单了!下边上代码~在backend目录创建components/AdminLog.php...
  • qq_31648761
  • qq_31648761
  • 2016-12-02 14:20:50
  • 1567

《web工程aop实现前台操作日志记录》初稿

写日志功能很繁琐,博主废了一些时间写出来分享,用的ssm框架,后期会设置优先级,避免所有方法都会被记录到日志。开始: 1、首先定义一个自定义注解@controllerLog和@serviceLog ...
  • zhou183911029
  • zhou183911029
  • 2017-05-04 16:41:11
  • 2438

服务端日志应该记录些啥

日志,类似于飞机或轮船上的“黑匣子”,在出现问题时应该提供给我们证据和解决问题的线索,那么具体而言日志应该记录些啥呢?日志应该如何分类和规划,以满足我们开发者的需求呢?         服务端的日志...
  • wang_zong_sheng
  • wang_zong_sheng
  • 2016-06-23 14:08:59
  • 1517

系统操作日志的实现原理

定义操作日志实体public class SystemOperationLog extends BaseEntity { /** * */ private stat...
  • u014344668
  • u014344668
  • 2017-06-16 15:17:05
  • 1345

一种用户操作日志信息的记录及读取方法

申请号:CN 201310364722 申请日期:2013年8月20日 申请人:苏州迈科网络安全技术股份有限公司【摘要】 本发明公开了一种用户操作日志信息的记录及读取方法,包括记录方法,具...
  • sentimentalBunny
  • sentimentalBunny
  • 2016-04-20 14:15:53
  • 8409

记录操作日志

在构造函数中使用注册一个会在php中止时执行的函数register_shutdown_function(), TP5框架中使用 $request = \think\Request::instan...
  • weixin_41624345
  • weixin_41624345
  • 2018-01-27 15:45:43
  • 105

PHP记录用户操作日志记录

  • weixin_36171533
  • weixin_36171533
  • 2018-01-06 11:41:21
  • 542

Linux下记录用户操作日志

注:此脚本直接执行即可 #!/bin/sbin #functions:install cmd_track scripts #date:2016-04-05 #auther:shaonbean #set...
  • wh211212
  • wh211212
  • 2016-10-10 12:03:57
  • 1512
收藏助手
不良信息举报
您举报文章:操作日志的内容记录及比对
举报原因:
原因补充:

(最多只允许输入30个字)