zoukankan      html  css  js  c++  java
  • mybatis拦截器处理

    1.自定义注释

    package com.hsfw.backyard.biz.security.authority;
    
    import java.lang.annotation.*;
    
    /**
     * 数据权限过滤自定义注解
     *
     * @Description
     * @Author: liucq
     * @Date: 2018/12/14
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface UserPermissionAop {
        String value() default "";
    }

    2.Utils

    package com.hsfw.backyard.biz.security.authority.util;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class ReflectUtil {
        /**
         * 利用反射获取指定对象的指定属性
         *
         * @param obj       目标对象
         * @param fieldName 目标属性
         * @return 目标属性的值
         */
        public static Object getFieldValue(Object obj, String fieldName) {
            Object result = null;
            Field field = ReflectUtil.getField(obj, fieldName);
            if (field != null) {
                field.setAccessible(true);
                try {
                    result = field.get(obj);
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * 利用反射获取指定对象里面的指定属性
         *
         * @param obj       目标对象
         * @param fieldName 目标属性
         * @return 目标字段
         */
        private static Field getField(Object obj, String fieldName) {
            Field field = null;
            for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
                try {
                    field = clazz.getDeclaredField(fieldName);
                    break;
                } catch (NoSuchFieldException e) {
                    // 这里不用做处理,子类没有该字段可能对应的父类有,都没有就返回null。
                }
            }
            return field;
        }
    
        /**
         * 利用反射设置指定对象的指定属性为指定的值
         *
         * @param obj        目标对象
         * @param fieldName  目标属性
         * @param fieldValue 目标值
         */
        public static void setFieldValue(Object obj, String fieldName, String fieldValue) {
            Field field = ReflectUtil.getField(obj, fieldName);
            if (field != null) {
                try {
                    field.setAccessible(true);
                    field.set(obj, fieldValue);
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    
    
        /**
         * 根据文件路径 获取反射对象并执行对应方法
         *
         * @author GaoYuan
         * @date 2018/4/17 上午9:51
         */
        public static Object reflectByPath(String path) {
            try {
                //获取类名
                String className = path.substring(0, path.lastIndexOf("."));
                //获取方法名
                String methodName = path.substring(path.lastIndexOf(".") + 1, path.length());
                // 获取字节码文件对象
                Class c = Class.forName(className);
    
                Constructor con = c.getConstructor();
                Object obj = con.newInstance();
    
                // public Method getMethod(String name,Class<?>... parameterTypes)
                // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
                Method method = c.getMethod(methodName);
                // 调用obj对象的 method 方法
                return method.invoke(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    package com.hsfw.backyard.biz.security.authority.util;//package com.foruo.sc.permission.example.util;
    
    import com.hsfw.backyard.biz.security.authority.UserPermissionAop;
    import org.apache.ibatis.mapping.MappedStatement;
    
    import java.lang.reflect.Method;
    
    
    public class PermissionUtils {
    
        public static UserPermissionAop getPermissionByDelegate(MappedStatement mappedStatement) {
            UserPermissionAop permissionAop = null;
            try {
                String id = mappedStatement.getId();
                String className = id.substring(0, id.lastIndexOf("."));
                String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
                final Class cls = Class.forName(className);
                final Method[] method = cls.getMethods();
                for (Method me : method) {
                    if (me.getName().equals(methodName) && me.isAnnotationPresent(UserPermissionAop.class)) {
                        permissionAop = me.getAnnotation(UserPermissionAop.class);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return permissionAop;
        }
    }

    3.mybatis

    package com.hsfw.backyard.biz.security.authority.mybatis;
    
    
    import com.hsfw.backyard.biz.ContextHolder;
    import com.hsfw.backyard.biz.model.sys.User;
    import com.hsfw.backyard.biz.security.authority.UserPermissionAop;
    import com.hsfw.backyard.biz.security.authority.util.PermissionUtils;
    import com.hsfw.backyard.biz.security.authority.util.ReflectUtil;
    import com.hsfw.backyard.dal.mapper.model.UserDataManageDO;
    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.MappedStatement;
    import org.apache.ibatis.plugin.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.sql.Connection;
    import java.util.List;
    import java.util.Properties;
    
    @Intercepts({
            @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
    })
    @Component
    public class PrepareInterceptor implements Interceptor {
    
        private static final Logger log = LoggerFactory.getLogger(PrepareInterceptor.class);
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
        }
    
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            if (log.isInfoEnabled()) {
                log.info("进入 PrepareInterceptor 拦截器...");
            }
            if (invocation.getTarget() instanceof RoutingStatementHandler) {
                RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
                StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate");
                //通过反射获取delegate父类BaseStatementHandler的mappedStatement属性
                MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
                BoundSql boundSql = delegate.getBoundSql();
                ReflectUtil.setFieldValue(boundSql, "sql", permissionSql(boundSql.getSql(), mappedStatement));
            }
            return invocation.proceed();
        }
    
        /**
         * 权限sql包装,以及是否需要包装
         *
         * @param sql
         * @return
         */
        protected String permissionSql(String sql, MappedStatement mappedStatement) {
            UserPermissionAop permissionAop = PermissionUtils.getPermissionByDelegate(mappedStatement);
            StringBuilder sbSql = new StringBuilder(sql);
            if (permissionAop != null) {
                String id = mappedStatement.getId();
                String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
                //方法过滤,待讨论
                if (methodName.equals("countByCondition") || methodName.equals("pageByCondition")) {
                    return getAppendSql(sbSql, methodName);
                }
            }
            return sbSql.toString();
        }
    
        /**
         * sql拼接
         *
         * @param sbSql
         * @param methodName
         * @return
         */
        public String getAppendSql(StringBuilder sbSql, String methodName) {
            //当前用户信息
            User user = ContextHolder.user();
            List<UserDataManageDO> managedUserList = user.getUserDatalist();
            String findUserList = String.valueOf(user.getId());
            for (int i = 0; i < managedUserList.size(); i++) {
                findUserList.concat("," + String.valueOf(managedUserList.get(i).getManagedUserId()));
            }
            if (methodName.equals("countByCondition")) {
                sbSql = sbSql.append(" and operate_user_id in (" + findUserList + ")  ");
            } else {
                sbSql = new StringBuilder("select * from (").append(sbSql).append(" ) temp where temp.operate_user_id in (" + findUserList + ")  ");
            }
            return sbSql.toString();
        }
    
    
    }
    package com.hsfw.backyard.biz.security.authority.mybatis;
    
    
    import com.hsfw.backyard.biz.security.authority.UserPermissionAop;
    import com.hsfw.backyard.biz.security.authority.util.PermissionUtils;
    import com.hsfw.backyard.biz.security.authority.util.ReflectUtil;
    import org.apache.ibatis.executor.resultset.ResultSetHandler;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.plugin.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.Properties;
    
    
    @Intercepts({
            @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
    })
    @Component
    public class ResultInterceptor implements Interceptor {
        /**
         * 日志
         */
        private static final Logger log = LoggerFactory.getLogger(ResultInterceptor.class);
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
        }
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            if (log.isInfoEnabled()) {
                log.info("进入 ResultInterceptor 拦截器...");
            }
            ResultSetHandler resultSetHandler1 = (ResultSetHandler) invocation.getTarget();
            //通过java反射获得mappedStatement属性值
            //可以获得mybatis里的resultype
            MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(resultSetHandler1, "mappedStatement");
            //获取切面对象
            UserPermissionAop permissionAop = PermissionUtils.getPermissionByDelegate(mappedStatement);
            //执行请求方法,并将所得结果保存到result中
            Object result = invocation.proceed();
            if (permissionAop != null) {
                if (result instanceof ArrayList) {
                    ArrayList resultList = (ArrayList) result;
                    for (int i = 0; i < resultList.size(); i++) {
                        Object oi = resultList.get(i);
                        Class c = oi.getClass();
                        Class[] types = {String.class};
                        Method method = c.getMethod("setRegionCd", types);
                        // 调用obj对象的 method 方法
                        method.invoke(oi, "");
                        if (log.isInfoEnabled()) {
                            log.info("数据权限处理【过滤结果】...");
                        }
                    }
                }
            }
            return result;
        }
    
    
    }
  • 相关阅读:
    eclipse自动生成uml
    【北航软件工程】Alpha阶段前端页面编写及服务器部署
    【北航软件工程】最长单词链
    软件工程第一次阅读!
    软工第0次个人作业
    第四次oo博客
    小菜鸡儿的第三次OO博客
    关于面向对象第二阶段的总结
    关于面向对象第一阶段的总结
    `ll/sc` 指令在`linux`中的软件实现
  • 原文地址:https://www.cnblogs.com/dand/p/10208420.html
Copyright © 2011-2022 走看看