框架:SpringBoot + Mybatis + Activiti7

思路:

单独给mybatis和activiti配置datasource

Mybati配置单数据源方法

单数据源只需要在yml中配置

url: jdbc:mysql://localhost:3306/localtest?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useSSL=false&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456

Mybati配置双数据源方法

给每个mybatis配置类分别设置数据源,然后使用MapperScan声明作用的mapper路径

此时url需要写成jdbc-url,不然会报错,欲知为何,待我看懂ConfigurationProperties咋起作用的
// 声明businessDataSource只作用于mapper路径下
@Configuration
@MapperScan(basePackages = "com.rsb.activitispringboot.mapper", sqlSessionFactoryRef = "businessSqlSessionFactory")
public class MybatisConfig {

    @Bean(name = "businessDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource businessDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "businessSqlSessionFactory")
    public SqlSessionFactory bizSqlSessionFactory(@Qualifier("businessDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
        return bean.getObject();
    }
    @Bean(name = "businessSqlSessionTemplate")
    public SqlSessionTemplate bizSqlSessionTemplate(@Qualifier("businessSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

activiti和mybaits分别配置数据源

activiti自己继承了mybaits,其mapper没有暴露,所以不能使用以上方法配置。

ativiti7有一个配置数据源的类ProcessEngineAutoConfiguration

@Bean
@ConditionalOnMissingBean // 不存在SpringProcessEngineConfiguration的bean的时候,才会注册这个bean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(
           DataSource dataSource,
           PlatformTransactionManager transactionManager,
           SpringAsyncExecutor springAsyncExecutor,
           ActivitiProperties activitiProperties,
           ProcessDefinitionResourceFinder processDefinitionResourceFinder,
           @Autowired(required = false) List\<ProcessEngineConfigurationConfigurer> processEngineConfigurationConfigurers,
           @Autowired(required = false) List\<ProcessEngineConfigurator> processEngineConfigurators) throws IOException {
       conf.setDataSource(dataSource);
//...}

也就是说同时存在mybaits的BusinessDatasource和ActivitiDatSource,而IOC容器单例模式不能有两个相同的bean,除非name不同,所以就有2种思路。

  • mybatis配置别名,activiti不配置
  • activiti配置别名,mybaits配置/不配置

1) mybatis配置别名,activiti不配置,这种方式简单,不用实现activiti的复杂编码。优先加载activiti的数据源

@Primary其作用与功能,当有多个相同类型的bean时,使用@Primary来赋予bean更高的优先级

@Configuration
@MapperScan(basePackages = "com.rsb.activitispringboot.mapper", sqlSessionFactoryRef = "businessSqlSessionFactory")
public class MybatisConfig {
    @Bean(name = "businessDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource businessDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "businessSqlSessionFactory")
    public SqlSessionFactory bizSqlSessionFactory(@Qualifier("businessDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "businessSqlSessionTemplate")
    public SqlSessionTemplate bizSqlSessionTemplate(@Qualifier("businessSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

@Configuration
public class ActivitiConfig{
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.activiti.datasource")
    public DataSource activitiDataSource() {
        return DataSourceBuilder.create().build();
    }
}

2) activiti配置别名,mybaits不配置 / 不配置

mybatis配置同上,可以使用Qualifier 也可以使用@Primary,建议@Qualifier,清晰明了

@Configuration
public class ActivitiConfig extends AbstractProcessEngineAutoConfiguration {

   @Bean("activitiDataSource")
   @ConfigurationProperties(prefix = "spring.activiti.datasource")
   public DataSource activitiDataSource() {
       return DataSourceBuilder.create().build();
   }

   @Bean("activitiTransactionManager")
   public PlatformTransactionManager txManager(@Qualifier("activitiDataSource") DataSource dataSource) {
       return new DataSourceTransactionManager(dataSource);
   }

   @Bean
   public SpringProcessEngineConfiguration springProcessEngineConfiguration(
           @Qualifier("activitiDataSource") DataSource dataSource,
           @Qualifier("activitiTransactionManager") PlatformTransactionManager transactionManager,
           SpringAsyncExecutor springAsyncExecutor,
           ActivitiProperties activitiProperties,
           ProcessDefinitionResourceFinder processDefinitionResourceFinder,
           @Autowired(required = false) List\<ProcessEngineConfigurationConfigurer> processEngineConfigurationConfigurers,
           @Autowired(required = false) List\<ProcessEngineConfigurator> processEngineConfigurators) throws IOException {
       SpringProcessEngineConfiguration conf = new SpringProcessEngineConfiguration();
       conf.setConfigurators(processEngineConfigurators);
       configureProcessDefinitionResources(processDefinitionResourceFinder,conf);
       conf.setDataSource(dataSource);
       conf.setTransactionManager(transactionManager);
       if (springAsyncExecutor != null) {
           conf.setAsyncExecutor(springAsyncExecutor);
       }
       conf.setDeploymentName(activitiProperties.getDeploymentName());
       conf.setDatabaseSchema(activitiProperties.getDatabaseSchema());        >>       conf.setDatabaseSchemaUpdate(activitiProperties.getDatabaseSchemaUpdate());
       conf.setDbHistoryUsed(activitiProperties.isDbHistoryUsed());
      conf.setAsyncExecutorActivate(activitiProperties.isAsyncExecutorActivate());
       if (!activitiProperties.isAsyncExecutorActivate()) {
           ValidatorSet springBootStarterValidatorSet = new ValidatorSet("activiti-spring-boot-starter");
           springBootStarterValidatorSet.addValidator(new AsyncPropertyValidator());
           if (conf.getProcessValidator() == null) {
               ProcessValidatorImpl processValidator = new ProcessValidatorImpl();
               processValidator.addValidatorSet(springBootStarterValidatorSet);
               conf.setProcessValidator(processValidator);
           } else {
 conf.getProcessValidator().getValidatorSets().add(springBootStarterValidatorSet);
           }
       }
       conf.setMailServerHost(activitiProperties.getMailServerHost());
       conf.setMailServerPort(activitiProperties.getMailServerPort());
       conf.setMailServerUsername(activitiProperties.getMailServerUserName());
       conf.setMailServerPassword(activitiProperties.getMailServerPassword());
       conf.setMailServerDefaultFrom(activitiProperties.getMailServerDefaultFrom());
       conf.setMailServerUseSSL(activitiProperties.isMailServerUseSsl());
       conf.setMailServerUseTLS(activitiProperties.isMailServerUseTls());
       conf.setUserGroupManager(userGroupManager);
       conf.setHistoryLevel(activitiProperties.getHistoryLevel());
conf.setCopyVariablesToLocalForTasks(activitiProperties.isCopyVariablesToLocalForTasks());
conf.setSerializePOJOsInVariablesToJson(activitiProperties.isSerializePOJOsInVariablesToJson());
conf.setJavaClassFieldForJackson(activitiProperties.getJavaClassFieldForJackson());
       if (activitiProperties.getCustomMybatisMappers() != null) {
conf.setCustomMybatisMappers(
getCustomMybatisMapperClasses(activitiProperties.getCustomMybatisMappers()));
       }
       if (activitiProperties.getCustomMybatisXMLMappers() != null) {
           conf.setCustomMybatisXMLMappers(new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
       }
       if (activitiProperties.getCustomMybatisXMLMappers() != null) {
           conf.setCustomMybatisXMLMappers(new HashSet<> activitiProperties.getCustomMybatisXMLMappers()));
       }
       if (activitiProperties.isUseStrongUuids()) {
           conf.setIdGenerator(new StrongUuidGenerator());
       }
       if (activitiProperties.getDeploymentMode() != null) {
           conf.setDeploymentMode(activitiProperties.getDeploymentMode());
       }
       conf.setActivityBehaviorFactory(new DefaultActivityBehaviorFactory());
       if (processEngineConfigurationConfigurers != null) {
           for (ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer : processEngineConfigurationConfigurers) {
               processEngineConfigurationConfigurer.configure(conf);
           }
       }
       return conf;
   }
   private void configureProcessDefinitionResources(
          ProcessDefinitionResourceFinder processDefinitionResourceFinder,
           SpringProcessEngineConfiguration conf) throws IOException {
       List<Resource> procDefResources = processDefinitionResourceFinder.discoverProcessDefinitionResources();
       if (!procDefResources.isEmpty()) {
           conf.setDeploymentResources(procDefResources.toArray(new Resource\[0]));
       }
   }
}