mybatis拦截器实现通用权限字段添加的方法

 更新时间:2019年09月18日 08:29:37   作者:木叔  
这篇文章主要给大家介绍了关于mybatis拦截器实现通用权限字段添加的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用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;
  }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • 基于Java代码实现支付充值的通用流程

    基于Java代码实现支付充值的通用流程

    本文给大家分享一段java核心代码实现支付充值的通用流程,非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-05-05
  • Scala隐式转换和隐式参数详解

    Scala隐式转换和隐式参数详解

    Scala隐式转换和隐式参数是两个非常强大的功能,它们可以让我们编写更灵活和优雅的代码,但也需要注意一些潜在的问题和风险,这篇文章主要介绍了Scala隐式转换和隐式参数,需要的朋友可以参考下
    2023-04-04
  • JDK17、JDK19、JDK1.8轻松切换(无坑版,小白也可以看懂!)

    JDK17、JDK19、JDK1.8轻松切换(无坑版,小白也可以看懂!)

    在做不同的java项目时候,因项目需要很可能来回切换jdk版本,下面这篇文章主要介绍了JDK17、JDK19、JDK1.8轻松切换的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Java中static修饰的静态变量、方法及代码块的特性与使用

    Java中static修饰的静态变量、方法及代码块的特性与使用

    这篇文章主要介绍了Java中static修饰的静态变量、方法及代码块的特性与使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Java使用fill()数组填充的实现

    Java使用fill()数组填充的实现

    这篇文章主要介绍了Java使用fill()数组填充的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • spring boot 下对JSON返回值去除null和空字段操作

    spring boot 下对JSON返回值去除null和空字段操作

    这篇文章主要介绍了spring boot 下对JSON返回值去除null和空字段操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • 在Spring使用iBatis及配置讲解

    在Spring使用iBatis及配置讲解

    今天小编就为大家分享一篇关于在Spring使用iBatis及配置讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Spring Cloud Feign的文件上传实现的示例代码

    Spring Cloud Feign的文件上传实现的示例代码

    这篇文章主要介绍了Spring Cloud Feign的文件上传实现的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • Redisson分布式锁源码解析

    Redisson分布式锁源码解析

    文章给大家分享了关于Redisson分布式锁源码相关的知识点内容,有兴趣的朋友们可以参考学习下。
    2018-08-08
  • 两种java实现二分查找的方式

    两种java实现二分查找的方式

    这篇文章主要给大家分享的是java实现二分查找的方式,二分查找是一种查询效率非常高的查找算法。又称折半查找。下面文章我们介绍了两种方法,需要的朋友可以参考一下
    2021-09-09

最新评论