盘点 Flow : Activiti 7 配置篇

首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> ???
文章合集 : ? juejin.cn/post/694164…
Github : ? github.com/black-ant

一 .前言

上一篇说了 ? activiti 7 的基本使用 , 这一篇来看一看 activiti 是怎么配置的

二 . 配置主流程

首先得知道 , 配置是哪里发起的 :

2.1 配置的起点

集成 Activiti-Spring 后 , 是通过 ProcessEngineAutoConfiguration 进行配置的 :

@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(ActivitiProperties.class)
public class ProcessEngineAutoConfiguration extends AbstractProcessEngineAutoConfiguration {

    private final UserGroupManager userGroupManager;

    public ProcessEngineAutoConfiguration(UserGroupManager userGroupManager) {
        this.userGroupManager = userGroupManager;
    }

    @Bean
    @ConditionalOnMissingBean
    public SpringProcessEngineConfiguration springProcessEngineConfiguration(
            DataSource dataSource,
            PlatformTransactionManager transactionManager,
            SpringAsyncExecutor springAsyncExecutor,
            ActivitiProperties activitiProperties,
            ProcessDefinitionResourceFinder processDefinitionResourceFinder,
            @Autowired(required = false) ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer) throws IOException {

        // 2.2 配置SpringProcessEngineConfiguration
        SpringProcessEngineConfiguration conf = new SpringProcessEngineConfiguration();
        configureProcessDefinitionResources(processDefinitionResourceFinder,conf);
        
        // 设置 DataSource 和 事务管理器
        conf.setDataSource(dataSource);
        conf.setTransactionManager(transactionManager);

        if (springAsyncExecutor != null) {
            // 设置 SpringAsyncExecutor -> PS:21001
            conf.setAsyncExecutor(springAsyncExecutor);
        }
        
        conf.setDeploymentName(activitiProperties.getDeploymentName());
        
        // 数据库更新类型  -> PS:21002
        conf.setDatabaseSchema(activitiProperties.getDatabaseSchema());
        conf.setDatabaseSchemaUpdate(activitiProperties.getDatabaseSchemaUpdate());
        
        
        conf.setDbHistoryUsed(activitiProperties.isDbHistoryUsed());
        conf.setAsyncExecutorActivate(activitiProperties.isAsyncExecutorActivate());
        
        // 配置邮件系统信息
        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());

        // 用户组管理器
        if (userGroupManager != null) {
            conf.setUserGroupManager(userGroupManager);
        }

        conf.setHistoryLevel(activitiProperties.getHistoryLevel());

        // 自定义 Mybatis Mapper
        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()));
        }

        // ID 生成器 : 基于当前时间和运行它的机器的以太网地址的实现
        if (activitiProperties.isUseStrongUuids()) {
            conf.setIdGenerator(new StrongUuidGenerator());
        }

        conf.setActivityBehaviorFactory(new CloudActivityBehaviorFactory());

        if (processEngineConfigurationConfigurer != null) {
            // 为 processEngineConfigurationConfigurer 设置配置
            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]));
        }
    }

    @Bean
    @ConditionalOnMissingBean
    public ProcessDefinitionResourceFinder processDefinitionResourceFinder(ActivitiProperties activitiProperties,
                                                                           ResourcePatternResolver resourcePatternResolver) {
        return new ProcessDefinitionResourceFinder(activitiProperties,
                                                   resourcePatternResolver);
    }

}

复制代码

PS:21002 SpringAsyncExecutor 的作用

作用 : 这是一个基于spring的Job Executor的实现,使用spring抽象TaskExecutor来执行后台任务

C- SpringAsyncExecutor
// 执行的简单任务执行器接口处理器
protected TaskExecutor taskExecutor;
// 处理已获取但此时不能执行(超过队列大小)的作业的策略
protected SpringRejectedJobsHandler rejectedJobsHandler;

复制代码

来看一下 TaskExecutor 的体系 ?

TaskExecutor-system.png

PS:21002 databaseSchemaUpdate属性的取值

databaseSchemaUpdate属性的取值:

flase: 默认值。在创建流程引擎时,根据库检查DB模式的版本,如果版本不匹配则抛出异常
true: 在构建流程引擎之后,如果有必要,将执行一次检查并对模式进行更新
create-drop:在创建流程引擎时创建模式,在关闭流程引擎时删除模式(必须手动关闭引擎,才能删除表)。
drop-create:在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。

这里有几个关注点 :

@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(ActivitiProperties.class)
复制代码

DataSourceAutoConfiguration 的作用 :

该文件是 org.springframework.boot.autoconfigure.jdbc 下的文件 , 因为 activiti 是有数据操作的 , 所以需要使用 DataSource , 这里是使用 Spring 的统一处理

ActivitiProperties 是什么 ?

@ConfigurationProperties("spring.activiti")
public class ActivitiProperties {

  private boolean checkProcessDefinitions = true;
  private boolean asyncExecutorActivate = false;
  private String deploymentName = "SpringAutoDeployment";
  private String mailServerHost = "localhost";
  private int mailServerPort = 1025;
  private String mailServerUserName;
  private String mailServerPassword;
  private String mailServerDefaultFrom;
  private boolean mailServerUseSsl;
  private boolean mailServerUseTls;
  private String databaseSchemaUpdate = "true";
  private String databaseSchema;
  private boolean isDbHistoryUsed = false;
  // 历史级别
  private HistoryLevel historyLevel = HistoryLevel.NONE;
  // 默认流程文档   
  private String processDefinitionLocationPrefix = "classpath:/processes/";
  // 流程配置文件后缀
  private List<String> processDefinitionLocationSuffixes = Arrays.asList("**.bpmn20.xml", "**.bpmn");
  // 允许自定义 DAO 操作   
  private List<String> customMybatisMappers;
  private List<String> customMybatisXMLMappers;
  private boolean useStrongUuids = true;

    
}

// 这里可以看到 ,  activiti 中提供了很多的配置 , 可以根据需求来配置 : 
HistoryLevel (none /activity / audit/full )


复制代码

2.3 配置的初始化

在上文 ProcessEngineAutoConfiguration 中 , 可以看到通过 new SpringProcessEngineConfiguration(); 构建该对象 , 实际上除了 ProcessEngineAutoConfiguration , 还有多个其他的对象 , 我们一个个来看一下 :

// Spring Activiti 7 的主要配置类包括以下几个 :
C- SpringProcessEngineConfiguration
C- JtaProcessEngineConfiguration
C- MultiSchemaMultiTenantProcessEngineConfiguration
C- StandaloneInMemProcessEngineConfiguration
C- StandaloneProcessEngineConfiguration

复制代码

我们来看一下分别做了什么 :

2.3.1 SpringProcessEngineConfiguration

C- SpringProcessEngineConfiguration
    E- ProcessEngineConfigurationImpl
    
    
这2个类非常的庞大 , 我们仅仅看其中一些重要的部分 : 
C- SpringProcessEngineConfiguration
    MC- SpringProcessEngineConfiguration : 其中配置了 AutoDeploymentStrategy 集合 -> PS:35001
    M- buildProcessEngine : 构建 ProcessEngine
    M- getUserGroupManager : 返回 UserGroupManager  -> PS:35002
    M- setTransactionSynchronizationAdapterOrder
    M- initDefaultCommandConfig : 初始化默认配置 -> PS:35003
    M- createTransactionInterceptor : 返回 SpringTransactionInterceptor
    M- initTransactionContextFactory : new 一个 SpringTransactionContextFactory -> PS:35004
    M- initJpa : 构建 JPA
    M- autoDeployResources
    M- setDataSource : 设置数据源 , 此处使用的数据源需要引入其他依赖产生或者使用 @Bean -> PS:35005
复制代码

PS:35001 AutoDeploymentStrategy 作用

作用 : 实现资源自动部署的策略接口。一个策略可以为它所提供的资源执行任何数量的部署.

策略能够处理对应于特定指定部署模式的部署。这种适用性可以使用#handlesMode(String)方法进行验证

AutoDeploymentStrategy 是一个接口 :
部署

C- AutoDeploymentStrategy
    M- boolean handlesMode(final String mode)
    	?- 确定该策略是否处理提供的部署模式的部署
    M- void deployResources(final String deploymentNameHint, final Resource[] resources, final RepositoryService repositoryService)
    	?- 对提供的资源执行部署,使用提供的名称作为提示,并使用提供的RepositoryService执行
复制代码

他有三种实现类 :

  • C- DefaultAutoDeploymentStrategy : 将所有资源组合到一个单独的部署中
  • C- ResourceParentFolderAutoDeploymentStrategy : 为共享同一父文件夹的每个资源集执行单独的部署
  • C- SingleResourceAutoDeploymentStrategy : 按名称对每个资源执行单独的部署

activiti-AutoDeploymentStrategy ?
activiti-AutoDeploymentStrategy.png

PS:35002 UserGroupManager

    
- List<String> getUserGroups(String username);
- List<String> getUserRoles(String username);
- List<String> getGroups();
- List<String> getUsers();


C- ActivitiUserGroupManagerImpl : 主要实现类
	F- UserDetailsService userDetailsService

    
    
// 通过 userDetailsService 获取相关的状态
@Override
public List<String> getUserGroups(String username) {

	return userDetailsService.loadUserByUsername(username).getAuthorities().stream()
                .filter((GrantedAuthority a) -> a.getAuthority().startsWith("GROUP_"))
                .map((GrantedAuthority a) -> a.getAuthority().substring(6))
                .collect(Collectors.toList());
}

@Override
public List<String> getUserRoles(String username) {
    
	return userDetailsService.loadUserByUsername(username).getAuthorities().stream()
                .filter((GrantedAuthority a) -> a.getAuthority().startsWith("ROLE_"))
                .map((GrantedAuthority a) -> a.getAuthority().substring(5))
                .collect(Collectors.toList());
}
复制代码

PS:35003 SpringTransactionInterceptor

C- SpringTransactionInterceptor
    E- AbstractCommandInterceptor  
复制代码

PS:35004 SpringTransactionContextFactory

public class SpringTransactionContextFactory implements TransactionContextFactory {
	
    // 这是Spring事务基础结构中的中心接口
	protected PlatformTransactionManager transactionManager;
	protected Integer transactionSynchronizationAdapterOrder;
    
    // .......
    
}
复制代码

PS:35005 构建 TransactionAwareDataSourceProxy

public ProcessEngineConfiguration setDataSource(DataSource dataSource) {
    if (dataSource instanceof TransactionAwareDataSourceProxy) {
      return super.setDataSource(dataSource);
    } else {
      // Wrap datasource in Transaction-aware proxy
      DataSource proxiedDataSource = new TransactionAwareDataSourceProxy(dataSource);
      return super.setDataSource(proxiedDataSource);
    }
}

复制代码

TransactionAwareDataSourceProxy 的作用

C- TransactionAwareDataSourceProxy
– 目标JDBC javax.sql的代理。数据源,添加spring管理事务的感知 , TransactionAwareDataSourceProxy是数据源代理/适配器链的最外层数据源 , TransactionAwareDataSourceProxy可以直接委托给目标连接池或一些中介代理/适配器

简单点说 : 没有Spring数据访问支持的数据访问代码可以与此代理一起无缝地参与Spring管理的事务

activiti-ProcessEngineConfigurationImpl ?
activiti-ProcessEngineConfigurationImpl.png

2.3.2 JtaProcessEngineConfiguration 的作用

作用 : 不使用Activiti的事务,使用JTA进行事务管理

Java Transaction API,通常称为JTA,是用于管理 Java中的事务的API , 简单说 , 就是 javax.transaction; 的体系结构

public class JtaProcessEngineConfiguration extends ProcessEngineConfigurationImpl {

    protected TransactionManager transactionManager;
    public CommandInterceptor createTransactionInterceptor() {
        // 可以看到 , 这里构建了一个 JtaTransactionInterceptor
        return new JtaTransactionInterceptor(transactionManager);
    }
    
    public void initTransactionContextFactory() {
        if (transactionContextFactory == null) {
            // 构建一个 JtaTransactionContextFactory 工厂类
            transactionContextFactory = new JtaTransactionContextFactory(transactionManager);
        }
    }
  
}
复制代码

2.3.3 MultiSchemaMultiTenantProcessEngineConfiguration

作用 : 多租户环境 , 构建多租户ProcessEngine的ProcessEngineConfiguration,其中每个租户都有自己的数据库模式


// 可以看到 ,注册的时候会带上 dataSource , 同时和 tenantId 绑定
public void registerTenant(String tenantId, DataSource dataSource) {
    ((TenantAwareDataSource) super.getDataSource()).addDataSource(tenantId, dataSource);
    
    if (booted) {
      createTenantSchema(tenantId);
      
      createTenantAsyncJobExecutor(tenantId);
      
      tenantInfoHolder.setCurrentTenantId(tenantId);
      super.postProcessEngineInitialisation();
      tenantInfoHolder.clearCurrentTenantId();
    }
}


  public ProcessEngine buildProcessEngine() {
    
    // 通过设置为null来禁用模式创建/验证
    String originalDatabaseSchemaUpdate = this.databaseSchemaUpdate;
    this.databaseSchemaUpdate = null; 
    
    boolean originalIsAutoActivateAsyncExecutor = this.asyncExecutorActivate;
    this.asyncExecutorActivate = false;
    
    ProcessEngine processEngine = super.buildProcessEngine();
    
    // 重置为原始值
    this.databaseSchemaUpdate = originalDatabaseSchemaUpdate;
    this.asyncExecutorActivate = originalIsAutoActivateAsyncExecutor;
    
    // 创建租户模式
    for (String tenantId : tenantInfoHolder.getAllTenants()) {
      createTenantSchema(tenantId);
    }
    
    // 开始异步执行程序
    if (asyncExecutor != null && originalIsAutoActivateAsyncExecutor) {
      asyncExecutor.start();
    }
    
    booted = true;
    return processEngine;
  }

复制代码

2.3.4 StandaloneInMemProcessEngineConfiguration

 // 使用内存数据库 , 此处使用的是 H2 
public StandaloneInMemProcessEngineConfiguration() {
    this.databaseSchemaUpdate = DB_SCHEMA_UPDATE_CREATE_DROP;
    this.jdbcUrl = "jdbc:h2:mem:activiti";
}
复制代码

简单点说 ,该配置会配置内存数据库的使用

总结

Activiti 7 配置篇基本上完成了 , 下一篇来看一看他的数据库操作>>

附录

??⚽✊??

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享