Fork me on GitHub

Mybatis拦截器使用实例_下面线键值转小写驼峰形式插件

  使用 Map 作为返回值时, Map 中的键值就是查询结果中的列名 ,而列名一般都是大小写字母或者下画线形式,和 Java中使用的驼峰形式不一致。而且由于不同数据库查询结果列的大小写也并不一致,因此为了保证在使用 Map 时的属性一致,可以对 Map 类型的结果进行特殊处理,即将不同格式的列名转换为Java 中的驼峰形式。这种情况下,我们就可以使用拦截器,通过拦截 ResultSetHandler接口中的 handleResultSets 方法去处理 Map 类型的结果。拦截器实现代码如下。
@Intercepts(
        @Signature(
                type = ResultSetHandler.class ,
                method = "handlerResultSets" ,
                args = {Statement.class}
        )
)
public class CameHumpinterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation ) throws Throwable{
        //先执行得到结果,在对结果进行处理
        List<Object> list = (List<Object>) invocation.proceed();
        for(Object object : list){
            //如果结果是Map类型,就对Map的key进行转换
            if(object instanceof Map){
                processMap((Map)object);
            }else {
                break;
            }
        }
        return list;

    }
    /*
    * 处理Map类型
    * */
    private void processMap(Map<String , Object> map){
        Set<String> keySet = new HashSet<String>(map.keySet());
        for(String key : keySet){
            //将以大写开头的字符串转换为小写,如采包含下画线也会处理为驼峰
            //此处只通过这两个简单的标识来判断是否进行转换
            if(key.charAt(0) >= 'A' && key.charAt(0) <= 'Z' || key.indexOf("_") >= 0){
                //取出原value值
                Object value = map.get(key);
                //将原key值去掉
                map.remove(key);
                //将转换好的key重新放入map中
                map.put(underlineToCamelhump(key) , value);

            }
        }

    }

    /*
    * 将下画线风格替换为驼峰风格
    * */
    public static String  underlineToCamelhump(String inputString){
        StringBuilder sb = new StringBuilder();

        //判断是否要对字符进行大写处理
        boolean nextUpperCase = false ;
        for(int i = 0 ; i <inputString.length() ; i++){
            char c = inputString.charAt(i);
            if(c == '_'){
                if(sb.length() > 0){
                    ////这时"_"在中间,需要对其后第一个字符进行大写处理,将标志修改为true
                    nextUpperCase = true;
                }

            }else {
                if(nextUpperCase){
                    //接上面,"_"后第一个字符进行大写处理,标志修改为false
                    sb.append(Character.toUpperCase(c));
                    nextUpperCase = false;
                }else{
                    //这里用于处理其他不需要特殊对待的字符,正常输出即可。
                    sb.append(Character.toLowerCase(c));
                }
            }
        }
        return sb.toString();
    }

    /*
     * target:拦截对象
     *
     * */
    @Override
    public Object plugin(Object target){
        // 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
        return (target instanceof RoutingStatementHandler)? Plugin.wrap(target,this):target;
    }
    //实现插件参数传递
    @Override
    public void setProperties(Properties properties){

    }
}
想要使用该插件,需要在 mybatis_config.xml中配置该插件。
<plugins>
        <plugin interceptor="com.example.simple.plugin.CameHumpinterceptor"></plugin>
    </plugins>
在上面拦截器代码执行中,invocation.proceed ()执行的结果被强制转换为了 List 类型,这是因为拦截器接口 ResultSetHandler 的handleResultSets 方法的返回值为 List 类型,所以
才能在这里直接强制转换,如果不知道这一点,就很难处理这个返回值,许多接口方法的返回值类型都是 List ,但是还有很多其他的类型,所以在写拦截器时,要根据被拦截的方法来确
定返回值的类型。
posted @ 2021-01-04 15:26  叶语婷  阅读(450)  评论(0编辑  收藏  举报