zhouxiang
2022-04-25 8ab2ad5580212b91df848e4c127f2a682485fde3
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
108
package com.hx.mybatis.aes.springbean;
 
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;
 
 
@Component
@Intercepts({
        @Signature(
                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class
        })
})
public class MySqlInterceptor implements Interceptor {
 
    private static Logger logger = LoggerFactory.getLogger(MySqlInterceptor.class.getName());
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
 
        // 方法一
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        //id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
        //String id = mappedStatement.getId();
        //sql语句类型 select、delete、insert、update
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        BoundSql boundSql = statementHandler.getBoundSql();
 
        // 获取节点的配置
        Configuration configuration = mappedStatement.getConfiguration();
        // 获取参数
        Object parameterObject = boundSql.getParameterObject();
        // MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作
        // MetaObject metaObject1 = configuration.newMetaObject(parameterObject);
        //获取sql中问号的基本信息
        List<ParameterMapping> parameterMappings = boundSql
                .getParameterMappings();
 
        /*for (ParameterMapping parameterMapping : parameterMappings) {
            String propertyName = parameterMapping.getProperty();
            System.out.println("propertyName:"+ propertyName);
            System.out.println("parameterObject:"+ parameterObject);
        }*/
 
        //这里可以进行sql修改
        //获取到原始sql语句
        String sql = boundSql.getSql();
        String sql2 = null;
        //新增
        if(sqlCommandType == SqlCommandType.INSERT){
            sql2 = SqlUtils.insertSql(sql, VariableAesKey.aesKeysTable);
        }else if(sqlCommandType == SqlCommandType.UPDATE){
            sql2 = SqlUtils.updateSql(sql, VariableAesKey.aesKeysTable);
        }else if(sqlCommandType == SqlCommandType.SELECT){
            if(VariableAesKey.isRun == 1){
                sql2 = SqlUtils.selectSql(sql, VariableAesKey.aesKeysTable);
            }else{
                sql2  = sql;
            }
        }else if(sqlCommandType == SqlCommandType.DELETE){
            sql2 = SqlUtils.deleteSql(sql, VariableAesKey.aesKeysTable);
        }else{
            sql2  = sql;
        }
 
        if(!"err".equals(sql2)){
            //通过反射修改sql语句
            Field field = boundSql.getClass().getDeclaredField("sql");
            field.setAccessible(true);
            field.set(boundSql, sql2);
        }
 
        return invocation.proceed();
 
    }
 
    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
 
    }
 
    @Override
    public void setProperties(Properties properties) {
 
    }
}