工作流系列(3)-Activiti初識

Activiti簡介

Activiti是一個開源的自動化業務工作流引擎,它是基於Apache許可的開源BPM平臺,支持最新的BPMN2.0流程引擎規範,是業界常用的工作流引擎之一

Activiti的優勢

  • 開源免費
  • 基於流行的語言Java
  • 支持圖形流程設計器,Eclipse,Web
  • 支持多種數據庫,Oracle、SQL Server、MySQL等
  • 簡單的串行流程時,能快速實現

Activiti的不足

  • 沒有任務軌跡 也就是說,無法記錄任務是怎麼來的,是由哪個任務結束等引起的
  • 只能按照流程圖流執行 如果流程圖中沒有連接,則不能執行

下載Activiti

我們可從Activiti官網單獨下載Activiti,也可以通過使用SpringBoot方式來集成Activiti。

官網下載

Activiti的最新版本已經到Activiti 7,不過因爲後續分析等都是基於Activiti 6版本,所以直接下載Activiti 6。文件結構如下圖所示:
Alt text
其中wars文件夾有三個war包,如下圖:
Alt text
將其中activiti-app.war拷貝到Tomcat的webapps 文件夾(其他web容器類似),然後啓動tomcat。
訪問http://localhost:8080/activiti-app/#/login路徑,用戶名:admin,密碼:test。
Alt text
登錄之後可以對其進行操作,包含一個在線流程設計器
Alt text
可以很方便的對流程進行編輯,修改

使用SpringBoot

我們創建一個SpringBoot項目並把Activiti加進去,在官網的指導文件有詳細步驟,以下只包括簡單步驟(假設已經對Springboot熟悉,如果不熟悉請看springboot官方文檔),添加Activity依賴:

<dependency>
	<groupId>org.activiti</groupId>
	<artifactId>activiti-spring-boot-starter-basic</artifactId>
	<version>${activiti.version}</version>
</dependency>

這就是所有需要執行的操作。

Activiti簡單使用

使用activiti進行工作流的開發,主要有三個步驟:

  1. 定義流程圖
  2. 部署流程圖
  3. 執行該流程圖

1)定義流程圖

定義流程既可以通過可視化方式進行,也可以通過編輯文本方式進行。而可視化方式分爲兩種,一種是Web方式,另外一種是通過Eclipse插件方式。下圖是一個定義好的流程圖。

2)部署流程圖

Activiti的核心是流程引擎,通過簡單配置流程引擎就可以使用,推薦使用Spring來配置。

2.1)配置流程引擎

2.1.1)使用activiti.cfg.xml 配置

最簡單的得到ProcessEngine的方式如下

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

通過在classpath路徑下尋找activiti.cfg.xml 配置文件來構造流程引擎,activiti.cfg.xml 的例子如下

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
       
  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="asyncExecutorActivate" value="false" />
    <property name="mailServerHost" value="mail.my-corp.com" />
    <property name="mailServerPort" value="5025" />
  </bean>

</beans>

通過對ProcessEngineConfiguration類進行解析獲得流程引擎,在配置文件中我們可以看到有對數據源的配置、對郵件服務器的配置、是否對數據庫進行升級、是否啓動Job,除了這些之外還有其他可配置的項,比如歷史、緩存、事務等,具體可參考官方文檔

activiti.cfg.xml必須包含一個id爲’processEngineConfiguration’的bean,上文使用的是單獨運行流程引擎:

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

目前可以使用的ProcessEngineConfiguration類有:

  • org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration: 單獨運行的流程引擎。Activiti會自己處理事務。 默認,數據庫只在引擎啓動時檢測 (如果沒有Activiti的表或者表結構不正確就會拋出異常)。
  • org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration:方便單元測試的輔助類。Activiti會自己控制事務。 默認使用H2內存數據庫。數據庫表會在引擎啓動時創建,關閉時刪除。 使用它時,不需要其他配置(除非使用job執行器或郵件功能)。
  • org.activiti.spring.SpringProcessEngineConfiguration:在Spring環境與Spring進行集成是使用的流程引擎。
  • org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration:運行在單獨模式下,並且使用JTA事務管理的流程引擎。

其他配置方式的示例

//使用默認配置
ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//使用鏈式方式配置
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
  .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
  .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
  .setJobExecutorActivate(true)
  .buildProcessEngine();
2.1.2)與Spring集成

將ProcessEngine當做一個普通的SpringBean來使用,通過org.activiti.spring.ProcessEngineFactoryBean來返回流程引擎,使用SpringProcessEngineConfiguration類來集成,具體配置信息如下:

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
  <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
2.1.3)事務

在於Spring集成時,有一個需要關注的點就是事務。
當把數據源(DataSource)傳遞給 SpringProcessEngineConfiguration (使用"dataSource"屬性)之後,Activiti內部使用了一個org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy代理來包裝傳遞進來的數據源(DataSource)。這樣做是爲了確保從數據源(DataSource)獲取的SQL連接能夠與Spring的事物很好的工作在一起。這意味它不再需要在你自己在Spring中配置代理數據源(dataSource)了。
當然它仍然允許你傳遞一個TransactionAwareDataSourceProxy到SpringProcessEngineConfiguration中,只不過在這個情形下SpringProcessEngineConfiguration不會對其進行額外的封裝。不過當你自己自定義TransactionAwareDataSourceProxy時,不要把其他已經被Spring事務管理的數據源傳遞進去。(比如 DataSourceTransactionManager 和 JPATransactionManager需要的是沒有被代理是數據源 )

2.2)發佈流程

要使用流程必須先將流程進行發佈,我們將定義好的流程圖放置到文件中(.bpmn20.xml 或 .bpmn後綴),然後這些文件將會被解析成一個個流程。

2.2.1)編程式部署

可以部署zip文件或bar文件

String barFileName = "path/to/process-one.bar";
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(barFileName));

repositoryService.createDeployment()
    .name("process-one.bar")
    .addZipInputStream(inputStream)
    .deploy();
2.2.2)流程定義的版本

BPMN中並沒有版本的概念,沒有版本也是不錯的,因爲可執行的BPMN流程作爲你開發項目的一部分存在版本控制系統的知識庫中(例如 SVN,Git 或者Mercurial)。 而在Activiti中,流程定義的版本是在部署時創建的。在部署的時候,流程定義被存儲到Activiti使用的數據庫之前,Activiti講會自動給 流程定義 分配一個版本號。

對於業務文檔中每一個的流程定義,都會通過下列部署執行初始化屬性key, version, name 和 id:

  • XML文件中流程定義(流程模型)的 id屬性被當做是流程定義的 key屬性。
  • XML文件中的流程模型的name 屬性被當做是流程定義的 name 屬性。如果該name屬性並沒有指定,那麼id屬性被當做是name。
  • 帶有特定key的流程定義在第一次部署的時候,將會自動分配版本號爲1,對於之後部署相同key的流程定義時候,這次部署的版本號將會設置爲比當前最大的版本號大1的值。該key屬性被用來區別不同的流程定義。

ps:流程定義中的id屬性被設置爲 {processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 這裏的generated-id是一個唯一的數字被添加,用於確保在集羣環境中緩存的流程定義的唯一性。

舉個流程的例子

<definitions id="myDefinitions" >
  <process id="myProcess" name="My important process" >
    ...

當部署了這個流程定義之後,在數據庫中的流程定義看起來像這樣:

Table 6.1.

id key name version
myProcess:1:676 myProcess My important proces 1

假設我們現在部署用一個流程的最新版本號(例如 改變用戶任務),但是流程定義的id保持不變。 流程定義表將包含以下列表信息:

Table 6.2.

id key name version
myProcess:1:676 myProcess My important proces 1
myProcess:2:870 myProcess My important proces 2

3)執行流程

3.1)Activiti提供的服務

提供的服務器

3.2)啓動流程

當我們將流程發佈之後,就可啓動流程了,啓動流程使用的是RuntimeService類,在該類中有很多相關方法用來啓動流程。

ProcessInstance startProcessInstanceByKey(String processDefinitionKey);

ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey);

ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
 

這裏簡單列舉了三種,當然還有其的方法都是用來啓動流程的

3.3)完成任務

所有關於任務的操作,都在TaskService中。


 void complete(String taskId);

 void complete(String taskId, Map<String, Object> variables);
 
 void complete(String taskId, Map<String, Object> variables, Map<String, Object> transientVariables);
 
 void complete(String taskId, Map<String, Object> variables, boolean localScope);

如果要完成任務,就是用上述幾個接口

參考資料

  1. Activiti官方用戶手冊
  2. Activiti5.16中文用戶手冊
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章