content: package org.ruoyi.config;
  
  import cn.hutool.core.net.NetUtil;
  import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
  import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler;
  import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
  import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
  import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
  import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
  import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
  import org.mybatis.spring.annotation.MapperScan;
  import org.ruoyi.aspect.DataPermissionAspect;
  import org.ruoyi.common.core.factory.YmlPropertySourceFactory;
  import org.ruoyi.common.core.utils.SpringUtils;
  import org.ruoyi.handler.InjectionMetaObjectHandler;
  import org.ruoyi.handler.MybatisExceptionHandler;
  import org.ruoyi.handler.PlusPostInitTableInfoHandler;
  import org.ruoyi.interceptor.PlusDataPermissionInterceptor;
  import org.springframework.beans.BeansException;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.PropertySource;
  import org.springframework.transaction.annotation.EnableTransactionManagement;
  
  /**
   * mybatis-plus配置类(下方注释有插件介绍)
   *
   * @author Lion Li
   */
  @EnableTransactionManagement(proxyTargetClass = true)
  @MapperScan("${mybatis-plus.mapperPackage}")
  @PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class)
  public class MybatisPlusConfig {
  
      @Bean
      public MybatisPlusInterceptor mybatisPlusInterceptor() {
          MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
          // 多租户插件 必须放到第一位
          try {
              TenantLineInnerInterceptor tenant = SpringUtils.getBean(TenantLineInnerInterceptor.class);
              interceptor.addInnerInterceptor(tenant);
          } catch (BeansException ignore) {
          }
          // 数据权限处理
          interceptor.addInnerInterceptor(dataPermissionInterceptor());
          // 分页插件
          interceptor.addInnerInterceptor(paginationInnerInterceptor());
          // 乐观锁插件
          interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
          return interceptor;
      }
  
      /**
       * 数据权限拦截器
       */
      public PlusDataPermissionInterceptor dataPermissionInterceptor() {
          return new PlusDataPermissionInterceptor(SpringUtils.getProperty("mybatis-plus.mapperPackage"));
      }
  
      /**
       * 数据权限切面处理器
       */
      @Bean
      public DataPermissionAspect dataPermissionAspect() {
          return new DataPermissionAspect();
      }
  
      /**
       * 分页插件，自动识别数据库类型
       */
      public PaginationInnerInterceptor paginationInnerInterceptor() {
          PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
          // 分页合理化
          paginationInnerInterceptor.setOverflow(true);
          return paginationInnerInterceptor;
      }
  
      /**
       * 乐观锁插件
       */
      public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
          return new OptimisticLockerInnerInterceptor();
      }
  
      /**
       * 元对象字段填充控制器
       */
      @Bean
      public MetaObjectHandler metaObjectHandler() {
          return new InjectionMetaObjectHandler();
      }
  
      /**
       * 使用网卡信息绑定雪花生成器
       * 防止集群雪花ID重复
       */
      @Bean
      public IdentifierGenerator idGenerator() {
          return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
      }
  
      /**
       * 异常处理器
       */
      @Bean
      public MybatisExceptionHandler mybatisExceptionHandler() {
          return new MybatisExceptionHandler();
      }
  
      /**
       * 初始化表对象处理器
       */
      @Bean
      public PostInitTableInfoHandler postInitTableInfoHandler() {
          return new PlusPostInitTableInfoHandler();
      }
  
      /**
       * PaginationInnerInterceptor 分页插件，自动识别数据库类型
       * https://baomidou.com/pages/97710a/
       * OptimisticLockerInnerInterceptor 乐观锁插件
       * https://baomidou.com/pages/0d93c0/
       * MetaObjectHandler 元对象字段填充控制器
       * https://baomidou.com/pages/4c6bcf/
       * ISqlInjector sql注入器
       * https://baomidou.com/pages/42ea4a/
       * BlockAttackInnerInterceptor 如果是对全表的删除或更新操作，就会终止该操作
       * https://baomidou.com/pages/f9a237/
       * IllegalSQLInnerInterceptor sql性能规范插件(垃圾SQL拦截)
       * IdentifierGenerator 自定义主键策略
       * https://baomidou.com/pages/568eb2/
       * TenantLineInnerInterceptor 多租户插件
       * https://baomidou.com/pages/aef2f2/
       * DynamicTableNameInnerInterceptor 动态表名插件
       * https://baomidou.com/pages/2a45ff/
       */
  
  }
  