zoukankan      html  css  js  c++  java
  • mybatis拦截器实现通用权限字段添加

    实现效果

    日常sql中直接使用权限字段实现权限内数据筛选,无需入参,直接使用,使用形式为:
    select * from crh_snp.channelinfo where short_code in (${commonEnBranchNo})

    注意事项说明

    1、添加插件若使用xml形式mybatis可在配置文件中plugins标签中添加,本项目实际使用的为注解形式mybatis,需要通过SqlSessionFactoryBean代码方式添加或者SqlSessionFactoryBean的xml配置形式,代码在jar包中无法操作,只能使用xml配置形式,故需要覆盖SqlSessionFactoryBean配置

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
       <property name="dataSource" ref="dataSource" />
       <property name="mapperLocations">
          <list>
             <value>classpath*:xmlmapper/*.xml</value>
             <value>classpath*:resources/xmlmapper/*.xml</value>
          </list>
       </property>
       <property name="plugins">
          <array>
             <bean class="com.cairh.xpe.snp.backend.interceptor.MybatisInterceptor"/>
          </array>
       </property>
    </bean>

    2、jdbc的jar包中配置了sqlSessionFactory,本项目中配置进行覆盖,注意spring中同名类后加载的会覆盖先加载的类,需要保证本项目配置的类后加载。spring配置文件扫描会先加载本工程项目bean,可通过新增额外的配置文件放在原配置文件后实现后加载,如

    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>
          classpath*:spring-beans.xml
          classpath*:spring-person.xml
       </param-value>
    </context-param>

    3、注意添加的参数需要${}形式使用,#{}会经过预编译获取到的sql参数为问号,无法直接替换

    拦截器实现类

    @Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
    })
    public class MybatisInterceptor implements Interceptor {
    
    //    private Logger logger = LoggerFactory.getLogger(getClass());
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
    
            if (invocation.getTarget() instanceof Executor && invocation.getArgs().length==4) {
                String sql = getSqlByInvocation(invocation);
                //将操作员可操作的渠道、用户id及营业部作通用字段放到sql中统一解析
                if(sql.contains("commonEnShortCode")){
                    sql = addPremissionParam(sql);
                    resetSql2Invocation(invocation, sql);
                }
            }
    
            return invocation.proceed();
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {}
    
    
    
        /**
         * 通用权限字段添加,目前支持:commonEnShortCode、commonEnBrokerUserId、commonEnBranchNo
         * @param sql
         * @return
         */
        private String addPremissionParam(String sql) {
            CrhUser crhUser = (CrhUser) RequestUtil.getRequest().getAttribute(CrhUser.CRH_USER_SESSION);
            BackendRoleServiceImpl backendRoleService = (BackendRoleServiceImpl)SpringContext.getBean("backendRoleServiceImpl");
            if(sql.contains("commonEnBranchNo")){
                List<String> enBranchNoList = backendRoleService.getEnBranchNo(crhUser.getUser_id());
                String enBranchNoSql = "select to_char(column_value) from TABLE(SELECT F_TO_T_IN('"+ StringUtils.join(enBranchNoList,",")+"') FROM DUAL)";
                sql = sql.replace("${commonEnBranchNo}", enBranchNoSql);
            }
            return sql;
        }
    
        /**
         * 获取当前sql
         * @param invocation
         * @return
         */
        private String getSqlByInvocation(Invocation invocation) {
            final Object[] args = invocation.getArgs();
            MappedStatement ms = (MappedStatement) args[0];
            Object parameterObject = args[1];
            BoundSql boundSql = ms.getBoundSql(parameterObject);
            return boundSql.getSql();
        }
    
        /**
         * 将sql重新设置到invocation中
         * @param invocation
         * @param sql
         * @throws SQLException
         */
        private void resetSql2Invocation(Invocation invocation, String sql) throws SQLException {
            final Object[] args = invocation.getArgs();
            MappedStatement statement = (MappedStatement) args[0];
            Object parameterObject = args[1];
            BoundSql boundSql = statement.getBoundSql(parameterObject);
            MappedStatement newStatement = newMappedStatement(statement, new BoundSqlSource(boundSql));
            MetaObject msObject =  MetaObject.forObject(newStatement, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(),new DefaultReflectorFactory());
            msObject.setValue("sqlSource.boundSql.sql", sql);
            args[0] = newStatement;
        }
    
        private MappedStatement newMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
            MappedStatement.Builder builder =
                    new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
            builder.resource(ms.getResource());
            builder.fetchSize(ms.getFetchSize());
            builder.statementType(ms.getStatementType());
            builder.keyGenerator(ms.getKeyGenerator());
            if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
                StringBuilder keyProperties = new StringBuilder();
                for (String keyProperty : ms.getKeyProperties()) {
                    keyProperties.append(keyProperty).append(",");
                }
                keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
                builder.keyProperty(keyProperties.toString());
            }
            builder.timeout(ms.getTimeout());
            builder.parameterMap(ms.getParameterMap());
            builder.resultMaps(ms.getResultMaps());
            builder.resultSetType(ms.getResultSetType());
            builder.cache(ms.getCache());
            builder.flushCacheRequired(ms.isFlushCacheRequired());
            builder.useCache(ms.isUseCache());
    
            return builder.build();
        }
    }
    public class BoundSqlSource implements SqlSource {
    
        private BoundSql boundSql;
    
        public BoundSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }
    
        @Override
        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }
    }
  • 相关阅读:
    js实现点击图片 弹出放大效果
    Linux 命令
    前台input输入框,输入内容并同步增加输入框长度
    Git
    Git 常用命令
    Windows环境git执行git add命令warning: ....
    Tomcat配置https、访问http自动跳转至https
    An internal error occurred during: "Importing Maven projects". Unsupported IClasspathEntry kind=4
    自定义滚动条mCustomScrollbar
    本地项目,发布至服务器
  • 原文地址:https://www.cnblogs.com/leskang/p/11535893.html
Copyright © 2011-2022 走看看