package com.ces;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;

import java.sql.Statement;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * @author SletZh
 * @Date 2019-12-29-17:24
 *
 * @see StatementHandler       具体拦截的类
 *  <E> List<E> query(Statement statement, ResultHandler resultHandler)
 *       throws SQLException;  具体拦截的方法
 *  拦截器的功能：
 *      在控制台输出带有实参的sql语句
 */
@Intercepts(value={@Signature(type= StatementHandler.class,method = "query",args={Statement.class, ResultHandler.class})})
@Slf4j
public class LogInterceptor implements Interceptor {

    /**
     *
     * @param invocation 代理类
     * @return  被代理方法的返回值
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        /*Method method = invocation.getMethod();*/
       /* Object[] args = invocation.getArgs();*/
        /*log.info(target.toString());
        log.info(method.getName());
        log.info(Arrays.toString(args));*/
        if(target instanceof RoutingStatementHandler){
            RoutingStatementHandler statement = (RoutingStatementHandler) target;
            BoundSql boundSql = statement.getBoundSql();
            String sql =boundSql.getSql();
            System.out.println("sql语句 ："+sql);
            Object parameterObject = boundSql.getParameterObject();
            if(parameterObject!=null) {
                HashMap paraMap=(HashMap)parameterObject;
                StringBuilder sb=new StringBuilder("==>");
                int i=1;
                List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
                for (ParameterMapping param:parameterMappings
                     ) {
                    String key = param.getProperty();
                    Object val = paraMap.get(key);
                    if(val instanceof CharSequence) {
                        //"\\?"匹配"?"
                        sql=sql.replaceFirst("\\?","\""+val+"\"");
                    }else {
                        sql=sql.replaceFirst("\\?",""+val);
                    }
                    sb.append("param"+i+" :"+val+"  ");
                    i++;
                }
                System.out.println(sb);
                System.out.println("执行sql ："+sql);
            }
        }
        long t1=System.currentTimeMillis();
        Object proceed = invocation.proceed();
        long t2=System.currentTimeMillis();
        if(proceed instanceof Object[]){
            System.out.println("执行结果 ："+ Arrays.toString((Object[]) proceed));
        }else {
            System.out.println("执行结果 ："+proceed);
        }
        System.out.println("执行时间为"+(t2-t1)+"ms");
        return proceed;
    }
}
