Flowable:ProcessEngine系列

Posted fntp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flowable:ProcessEngine系列相关的知识,希望对你有一定的参考价值。

Flowable-ProcessEngine

Flowable-ProcessEngine流程引擎系列(1)

        在Flowable中,流程的实现是依托于各个组件的相互依赖、组合而成的。ProcessEngine流程引擎是纵观整个Flowable应用的关键。通过构建ProcessEngine,我们可以从中拿到History的服务,Management服务,Repository服务,Form服务,Identity服务,Runtime服务以及Task服务。因此对于Flowable中的Engine,我们需要详细地去了解学习。本文会将Flowable的Engine的学习记录分几个部分作为讲解,由浅入深,全面的学习并掌握Flowable的Engine组件。

一、构建ProcessEngine

常规方法:参数填充

        构建一个ProcessEngine,我们肯定不会避开配置,关于Flowable的配置,有很多种,但在实际开发中,我们一般常用声明式编程的方式进行配置,结合Spring的解析,我们可以依托于SpringCloud组件Nacos构建配置中心,以编程的方式去加载读取配置中心中Flowable的配置,进而通过填补ProcessEngine的配置类信息,来构建ProcessEngine。

        在Flowable6.7.2中,Engine的构建来自于ProcessEngineConfiguration这个类,我们来看一下这类的具体情况:

        当前版本6.7.2下这个类的实现结构图如下图所示:


        但在Flowable6.5之前,ProcessEngine的配置类:ProcessEngineConfiguration的生态结构如下图所示:

        通过比较可以发现,在6.7.2中,flowable删除了关于Spring的配置类,新增了一个多引擎多系统配置类,从而达到一个配置类,以制定路由规则的方式支持多个数据库操作,这个场景用于多租户的情况。(租户也是一种互联网架构,这种技术后面会有一篇专题来解释说明)接下来我们重点关注一下6.7.2版本中的五个配置类:

类名作用应用场景
StandaloneProcessEngineConfiguration流程引擎以独立的方式使用。Flowable 将处理所有交易。默认情况下,只会在引擎启动时检查数据库(如果没有 Flowable 架构或架构版本不正确,则会引发异常)。-
StandaloneInMemProcessEngineConfiguration这是一个用于单元测试的便利类。Flowable 将处理所有交易。默认使用 H2 内存数据库。当引擎启动和关闭时,将创建和删除数据库。使用它时,可能不需要额外的配置(例如,使用作业执行器或邮件功能时除外)。-
JtaProcessEngineConfiguration当引擎以独立模式运行时使用,带有 JTA 事务。事务管理
ProcessEngineConfigurationImpl如果我们想自定义一个ProcessEngineConfiguration抽象类可以选择继承ProcessEngineConfiguration或者它的直接子类ProcessEngineConfigurationImpl,继承ProcessEngineConfigurationImpl需要实现getDefaultCommandInterceptorsTxRequired和getDefaultCommandInterceptorsTxRequiresNew方法。如果需要添加自定义属性,可以为自己的ProcessEngineConfiguration类添加属性,并且添加相应的setter方法。自定义配置
MultiSchemaMultiTenantProcessEngineConfiguration以制定路由规则的方式支持多个数据库操作多租户
        所以对于我们日常使用而言,没有必要去对底层的细节掌握的炉火纯青,除非自己去构建一个流程应用,或者是改写流程。但是如果是自定义定制个性化的流程,那么对于ProcessEngineConfiguration的直接子类:ProcessEngineConfigurationImpl需要深入去了解一番。我们只需要关心创建流程的几种常用的方式就可以了。需要注意的是:所有这些 ProcessEngineConfiguration.createXXX() 方法都返回一个 ProcessEngineConfiguration ,如果需要可以进一步调整。调用 buildProcessEngine() 操作后,会创建一个 ProcessEngine,这种模式源自于Java的构建者模式:
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
  .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
  .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
  .setAsyncExecutorActivate(false)
  .buildProcessEngine();
快速创建:默认规范

        而对于只是想快速体验的同学来说,有更直接的方式来创建ProcessEngine:

ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
快速创建:依赖注入(XML方式)

        通过构建ProcessEngineConfiguration的Bean进行依赖属性的注入也是一种快速构建ProcessEngine的方式。这种方式依赖于一个Spring的bean配置文件,也就是Spring的applicationContext.xml,在flowable应用中,一般名字为:flowable.cfg.xml ,文件名都不是重点,重点是必须包含一个 id为“processEngineConfiguration”的 bean。

 <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        然后使用这个 bean 来构造 ProcessEngine。有多个类可用于定义 processEngineConfiguration。这些类代表不同的环境,并相应地设置默认值。最佳实践是选择与您的环境最匹配的类,以尽量减少配置引擎所需的属性数量。上文中也已经提及了这些类的具体用处以及使用场景,这里就不过多赘述。

二、ProcessEngine核心内容


        ProcessEngine,引擎 API 是与 Flowable 交互的最常见方式。主要起点是 ProcessEngine,它可以通过配置部分中描述的多种方式创建。您可以从 ProcessEngine 获取包含工作流/BPM 方法的各种服务。ProcessEngine 和服务对象是线程安全的,因此您可以为整个服务器保留对其中之一的引用。

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 基于ProcessEngine获得Service服务
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();

        ProcessEngines.getDefaultProcessEngine() 将在第一次调用时初始化并构建流程引擎,然后始终返回相同的流程引擎。可以使用 ProcessEngines.init() 和 ProcessEngines.destroy() 正确创建和关闭所有流程引擎。

        ProcessEngines 类将扫描所有 flowable.cfg.xmlflowable-context.xml 文件。对于所有 flowable.cfg.xml 文件,流程引擎将以典型的 Flowable 方式构建:ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()。对于所有 flowable-context.xml 文件,流程引擎将以 Spring 方式构建:首先创建 Spring 应用程序上下文,然后从该应用程序上下文中获取流程引擎。

        所有服务都是无状态的。这意味着您可以轻松地在集群中的多个节点上运行 Flowable,每个节点都访问同一个数据库,而不必担心哪台机器实际执行了先前的调用。无论在何处执行,对任何服务的任何调用都是幂等的。

三、ProcessEngine配置解读

        接下来,我们将会针对ProcessEngine的源码做一定程度的解读。首先我们先熟知一下,ProcessEngine内部,都有些什么内容,启动配置解读主要是为了让大家知晓,ProcessEngine的代码背后,主要的意图在哪里。我们现在看下面代码,能知道ProcessEngine接口内部的情况:

(1)启动解释器方法,也就是启动ProcessEngine引擎;

(2)在Flowable6.7.2中,一共有九个内部API服务方法;

(3)装载本地配置的流程配置对象。


        我们首先看以下代码:以下代码旨在创建Flowable工作流的配置对象,设置驱动全限定类名,设置jdbc连接用户名,设置连接密码,设置连接数据库的数据库连接地址,设置数据库策加载策略。

package org.flowable.springboot.demo.config;
import org.flowable.common.engine.impl.AbstractEngineConfiguration;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;

/**
 * @author fntp
 */
@Component
public class MyProcessEngineConfiguration 

    @Resource
    private DataSourceProperties properties;

    /**
     * 获得一个ProcessEngine配置对象
     * @return 返回一个ProcessEngine的mysql配置对象
     */
    public ProcessEngineConfiguration getConfiguration()
        return new StandaloneProcessEngineConfiguration().setJdbcDriver(properties.getDriverClassName())
                .setJdbcUsername(properties.getUsername())
                .setJdbcPassword(properties.getPassword())
                .setJdbcUrl(properties.getUrl())
                .setDatabaseSchemaUpdate(AbstractEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    

        Flowable6.7.2中,构建ProcessEngineConfiguration的方式多种多样,但最终目的,仍旧是为了构建ProcessEngine。


        即使配置类的形式多种多样,但是通过ProcessEngineConfiguration来构建ProcessEngine的方式就那么简单:就是直接buildProcessEngine。

        我们直接看一下FLowable是如何在直接子类中做的实现:

    public ProcessEngine buildProcessEngine() 
        // 首先是一些列的Init初始化方法,吧所有待加载的对象全部初始化
        this.init();
        // 创建一个ProcessEngine的实现类对象,将当前配置对象作为参数传递进去
        ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
        // 如果流程引擎解释器控制器在流程启动后加载成功
        if (this.handleProcessEngineExecutorsAfterEngineCreate) 
            // 那么直接调用流程引擎对象的内部API,启动解释器
            processEngine.startExecutors();
        
		// 如果启动了Flowable内部的兼容器 并且 兼容器控制器也初始化成功
        if (this.flowable5CompatibilityEnabled && this.flowable5CompatibilityHandler != null) 
            // 命令解释器解析指令
            this.commandExecutor.execute(new Command<Void>() 
                // 具体解析的过程
                public Void execute(CommandContext commandContext) 
                    ProcessEngineConfigurationImpl.this.flowable5CompatibilityHandler.getRawProcessEngine();
                    return null;
                
            );
        
		// 流程引擎的进一步初始化
        this.postProcessEngineInitialisation();
        // 返回流程引擎对象
        return processEngine;
    

	// 流程引擎的进一步初始化
     protected void postProcessEngineInitialisation() 
            if (this.validateFlowable5EntitiesEnabled) 
                this.commandExecutor.execute(new ValidateV5EntitiesCmd());
            

            if (this.redeployFlowable5ProcessDefinitions) 
                this.commandExecutor.execute(new RedeployV5ProcessDefinitionsCmd());
            

            if (this.performanceSettings.isValidateExecutionRelationshipCountConfigOnBoot()) 
                this.commandExecutor.execute(new ValidateExecutionRelatedEntityCountCfgCmd());
            

            if (this.performanceSettings.isValidateTaskRelationshipCountConfigOnBoot()) 
                this.commandExecutor.execute(new ValidateTaskRelatedEntityCountCfgCmd());
            

            if (this.flowable5CompatibilityEnabled) 
                this.flowable5CompatibilityHandler.setJobProcessor(this.flowable5JobProcessors);
            

        

        接下来我们看一下一段初始化代码,看看这段代码在整个ProcessEngine的加载工程中起到了什么作用吧!

// 关键语句
this.init();

以下是ProcessEngine中,Init方法的总览:

        我们直接把代码粘贴下来做一下详细解释吧!由于篇幅原因,我这里只讲需要关注的地方了。如果按照我的上面的博客:一个简单流程中那样,对Flowable的日志打印做了配置,那么你肯定能看见,在项目初始化的时候,如果你配置了JDBC相关数据信息后,启动项目时,会有源源不断的日志打印,如果你是第一次启动项目,数据库中没有相关数据表,那么你会看见日志中显示系统在执行SQL,当然,这些都是在流程引擎完成了配置之后进行的任务,那他是怎么加载的配置呢?我们仔细看如下代码:

public void init() 
	// 加载关系型数据库数据源
    if (this.usingRelationalDatabase) 
        this.initDataSource();
     else 
        // 加载非关系型数据库数据源
        this.initNonRelationalDataSource();
    
	// 是否使用关系型数据库,加载数据库管理器
    if (this.usingRelationalDatabase || this.usingSchemaMgmt) 
        this.initSchemaManager();
        this.initSchemaManagementCommand();
    
	// 初始化sqlSession
    if (this.usingRelationalDatabase) 
        this.initSqlSessionFactory();
    

        相比看到这里,肯定拨云见雾了。在ProcessEngine的build方法中,其中的init函数,就囊括了对数据源数据驱动的配置初始化,当我们配置完毕ProcessEngineConfiguration之后,它会自动去加载这个配置类,然后执行数据库的相关的初始化工作,因此,日志中那些log,就是这么来的。

四、总结

        好了,本文主要对ProcessEngine构建过程中的数据库配置以及启动过程中的源码进行了一个简单的解读。接下来的下文中,将会对Flowable的ProcessEngine中,一个ProcessEngine构建的真的流程,完整的给大家解读一番。更多精彩,尽在码农修炼笔记!

以上是关于Flowable:ProcessEngine系列的主要内容,如果未能解决你的问题,请参考以下文章

Flowable:ProcessEngine系列

Flowable:ProcessEngine系列

Flowable:ProcessEngine系列

Flowable:ProcessEngine系列

Flowable入门系列文章11 - Flowable API 01

flowable ProcessEngine和ProcessEngineConfiguration