主要实现的功能是两个数据库之前数据的同步(保证两个数据库的数据相同)
思路:
1.mybatis拦截系统执行的增加、删除、修改的SQL
2.拦截到的SQL进行base64加密存入数据库的记录表中
3.使用线程池调用相关的接口把拦截的SQL在另一个系统中执行
主要代码:
1.拦截SQL保存并调用相关接口
import com.baomidou.mybatisplus.toolkit.IdWorker;
import dc.platform.admin.common.utils.IpUtil;
import dc.platform.admin.common.utils.SysHttpClient;
import dc.platform.admin.common.utils.UtilValidate;
import dc.platform.admin.modules.sys.controller.AbstractController;
import dc.platform.admin.modules.sys.entity.SysUserEntity;
import dc.platform.common.utils.SpringContextUtils;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
/**
* @author MengyuWu
* @Title: ${file_name}
* @Package ${package_name}
* @Description: ${todo}
* @date 2018/3/21 16:15
*/
@Intercepts({
@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class })
})
@Component
public class MybatisInterceptor extends AbstractController implements Interceptor {
@Value("${SynURL}")
private String url;
@Override
public Object intercept(Invocation invocation) throws Throwable {
//获取当前请求
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//加载jdbc
JdbcTemplate jdbcTemplate = (JdbcTemplate)SpringContextUtils.getBean("jdbcTemplate");
try{
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; // 获取xml中的一个select/update/insert/delete节点,主要描述的是一条SQL语句
Object parameter = null;
// 获取参数,if语句成立,表示sql语句有参数,参数格式是map形式
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
System.out.println("parameter = " + parameter);
}
String sqlId = mappedStatement.getId(); // 获取到节点的id,即sql语句的id
System.out.println("sqlId = " + sqlId);
BoundSql boundSql = mappedStatement.getBoundSql(parameter); // BoundSql就是封装myBatis最终产生的sql类
Configuration configuration = mappedStatement.getConfiguration(); // 获取节点的配置
String sql = showSql(configuration, boundSql); // 获取到最终的sql语句
System.out.println("sql = " + sql);
//过滤系统操作记录表
if (!sql.contains("sys_record_oper")) {
Base64.Encoder encoder = Base64.getEncoder();
byte[] textByte = sql.getBytes("UTF-8");
//编码
String enSql = encoder.encodeToString(textByte);
System.out.println("enSql = " + enSql);
//获取当前登录人信息
SysUserEntity user = getUser();
//获取ip
String ip=IpUtil.getIpAddr(request);
//线程池调用相关的接口
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
//多线程池执行线程任务
fixedThreadPool.execute(new MyThread(url, enSql, user.getDeptId().toString()));
//拼接相关的保存系统操作记录的SQL
String insertsql="insert into sys_record_oper (id,method,oper_sql,ip,dept_id,last_upd_time,last_upd_person_id,last_upd_person_name) VALUES('"+IdWorker.getId()+"','"+sqlId+"','"+enSql+"','"+ip+"','"+user.getDeptId().toString()+"',NOW(),'"+user.getUserId().toString()+"','"+user.getUsername()+"');";
//执行保存到系统记录表中的SQL
jdbcTemplate.execute(new ConnectionCallback
2.系统接口方法
//系统接口
// @RequestMapping(value = "/synDate", method = RequestMethod.POST)
@RequestMapping("/synData")
@ResponseBody
public String synDate(@RequestBody JSONObject args, HttpServletRequest request)
{
JSONObject result = new JSONObject();
//获取部门id
String deptId = args.get("deptId").toString();
String ensql=args.get("ensql").toString();
//base64编码sql
Base64.Decoder decoder = Base64.getDecoder();
//执行接口传过来的SQL同步相关数据
try {
final String deSql = new String(decoder.decode(ensql), "UTF-8");
jdbcTemplate.execute(new ConnectionCallback