背景需求
项目中使用的持久层框架Mybatis,我们使用MongoDB记录所有的更新历史记录,方便项目出问题时便于分析。将所有的数据的更新,即新增修改删除的记录,都记录在MongoDB中,可以通过RockMongo这个工具查找。
实现
自己写了一个拦截器,用于拦截Executor执行器的Update方法。通过解析参数,在目标方法即Update方法执行前后对数据进行处理,最终将数据记录到MongoDB中。
package com.sk.sams.common.mybatis.changemonitor;
import java.util.List;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import com.sk.sams.common.mybatis.changemonitor.domain.ChangeData;
import com.sk.sams.common.mybatis.changemonitor.listener.ChangeEventListener;
import com.sk.sams.common.mybatis.changemonitor.mybatis.MybatisInvocation;
import com.sk.sams.common.mybatis.changemonitor.parse.DataPaser;
import com.sk.sams.common.mybatis.changemonitor.parse.ParseFactory;
/**
* 拦截器,拦截Executor的Update方法,即数据库的更新操作,Insert,Update,Delete都会拦截
* @author sailing.yang
*
*/
@Intercepts(value = {
@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class ChangeMinitorInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拦截目标
Object target = invocation.getTarget();
Object result = null;
if (target instanceof Executor) {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
String commandName = ms.getSqlCommandType().name();
ChangeEventListener changeEventListener = ChangeEventListener.getInstance();
DataPaser dataPaser = ParseFactory.getInstance().creator(commandName);
MybatisInvocation mybatisInvocation = new MybatisInvocation(args, ms, parameter, (Executor) target);
// 方法执行之前解析数据
List<ChangeData> changeTable = dataPaser.parseBefore(commandName, mybatisInvocation);
// 执行Update方法,除了查询之外的Insert,Delete,Update都是属于Update方法
result = invocation.proceed();
// 方法执行之后处理数据
changeTable = dataPaser.parseAfter(mybatisInvocation, changeTable);
if (changeTable != null) {
changeEventListener.listenModification(commandName, changeTable);
}
}
return result;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties arg0) {
}
}
这个拦截器需要配置在mybatis的配置文件中:
<plugins>
<plugin interceptor="com.sk.sams.common.mybatis.changemonitor.ChangeMinitorInterceptor" />
</plugins>
MongoDB效果
可以很清晰地在MongoDB中记录是哪个表,更新了哪些字段,更新的前后值是什么。
如果想要源码,请去这里下载,需要5积分哟。