首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> ???
文章合集 : ? 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 的体系 ?
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 ?
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 ?
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 配置篇基本上完成了 , 下一篇来看一看他的数据库操作>>
附录
??⚽✊??