文章目錄
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。文件結構如下圖所示:
其中wars文件夾有三個war包,如下圖:
將其中activiti-app.war拷貝到Tomcat的webapps 文件夾(其他web容器類似),然後啓動tomcat。
訪問http://localhost:8080/activiti-app/#/login路徑,用戶名:admin,密碼:test。
登錄之後可以對其進行操作,包含一個在線流程設計器
可以很方便的對流程進行編輯,修改
使用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)定義流程圖
定義流程既可以通過可視化方式進行,也可以通過編輯文本方式進行。而可視化方式分爲兩種,一種是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);
如果要完成任務,就是用上述幾個接口