一:什麼是Activiti
Activiti是一個開源的工作流引擎,它實作了BPMN 2.0規範,可以釋出設計好的流程定義,并通過api進行流程排程。
業務流程模型注解(Business Process Modeling Notation - BPMN)是 業務流程模型的一種标準圖形注解。包括使用者任務,定時任務都有統一的模型規範。
Activiti 作為一個遵從 Apache 許可的工作流和業務流程管理開源平台,其核心是基于Java的超快速、超穩定的 BPMN2.0 流程引擎,強調流程服務的可嵌入性和可擴充性,同時更加強調面向業務人員。
在項目中,Activiti實際上相當于一個第三方插件幫助原本系統業務更好的執行,Activiti本身并沒有任何業務邏輯。
二:為什麼需要引入Activiti工作流
舉個例子:
如果我們要開發一套請假流程,具體流程如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNyZuBnLwQzNxEzNxEjM5EDOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
在沒有Activiti工作流引擎幫助下,我們會怎麼設計表結構?預設模式下,應該會設計兩張表,一張來存請假内容,一張來存請假審批過程。隻有總經理和HR人力能夠批改。假設當我們設計好表後,需求改變了,經理審批這個節點改成組長審批,那這個時候,我們是不是又要修改代碼或者表結構?
這個時候Activiti引擎起作用。我們不會把具體節點人寫死,而是可以在流程過程中指定。
三:如何使用Activiti
Activiti使用時注意的概念
1.儲存流程圖—>相當于将流程圖存到activiti資料庫中,此時是靜态資源。
2.釋出流程---->相當java中的類,如果開始節點部署的普通的開始事件,則不會自動啟動流程,如果裡面開始節點使用定時事件,則到時間便會自動啟動流程執行個體(可以内置定時事件應用到TCL電子的點檢任務)。
3.啟動流程執行個體—>相當java中的對象
1.每個節點的任務都指定具體人
@RequestMapping(value="/model/{modelId}/save", method = RequestMethod.PUT)
@ResponseStatus(value = HttpStatus.OK)
public void saveModel(@PathVariable String modelId
, String name, String description
, String json_xml, String svg_xml) {
try {
Model model = repositoryService.getModel(modelId);
ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
modelJson.put(MODEL_NAME, name);
modelJson.put(MODEL_DESCRIPTION, description);
model.setMetaInfo(modelJson.toString());
model.setName(name);
repositoryService.saveModel(model);
repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes(“utf-8”));
InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes(“utf-8”));
TranscoderInput input = new TranscoderInput(svgStream);
PNGTranscoder transcoder = new PNGTranscoder();
// Setup output
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);
// Do the transformation
transcoder.transcode(input, output);
final byte[] result = outStream.toByteArray();
repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();
} catch (Exception e) {
LOGGER.error(“Error saving model”, e);
throw new ActivitiException(“Error saving model”, e);
}
}
@ResponseBody
@RequestMapping("/publish")
public Object publish(String modelId){
logger.info(“流程部署入參modelId:{}”,modelId);
Map<String, String> map = new HashMap<String, String>();
try {
Model modelData = repositoryService.getModel(modelId);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (bytes == null) {
logger.info(“部署ID:{}的模型資料為空,請先設計流程并成功儲存,再進行釋出”,modelId);
map.put(“code”, “FAILURE”);
return map;
}
JsonNode modelNode = new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
Deployment deployment = repositoryService.createDeployment()
.name(modelData.getName())
.addBpmnModel(modelData.getKey()+".bpmn20.xml", model)
.deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);
map.put(“code”, “SUCCESS”);
} catch (Exception e) {
logger.info(“部署modelId:{}模型服務異常:{}”,modelId,e);
map.put(“code”, “FAILURE”);
}
logger.info(“流程部署出參map:{}”,map);
return map;
}
@Test
public void completeTask() {
List list = taskService.createTaskQuery().taskAssignee(“張三”).list();
for (Task task : list) {
taskService.complete(task.getId());
}
}
2.節點代理人是動态的
流程變量概念:相當于局部變量,使用範圍在目前執行個體内有效
@Test
public void startProcessInstance() {
Map<String, Object> map = new HashMap<>();
map.put(“name”, “張三”);
runtimeService.startProcessInstanceByKey(“process”,map);
}
3.流程分支控制
@Test
public void completeTask() {
List list = taskService.createTaskQuery().taskAssignee(“張三”).list();
for (Task task : list) {
taskService.setVariable(task.getId(),“num”,2);
taskService.complete(task.getId());
}
}
@Test
public void completeTask() {
List list = taskService.createTaskQuery().taskAssignee(“張三”).list();
for (Task task : list) {
Map<String, Object> map = new HashMap<>();
map.put(“num”, 2);
taskService.complete(task.getId(),map);
}
}
4.候選人和候選組
在實作上,候選人和候選組是一樣的
假設總經理有多個人可以審批請假流程,那我們不能把審批人固定為某個人。我們可以直接寫死候選人,也可以将候選人設定為流程變量,然後在流程執行過程中設定變量值。
@Test
public void claimTask() {
List list = taskService.createTaskQuery().taskCandidateUser(“劉備”).list();
for (Task task : list) {
taskService.claim(task.getId(), "劉備");
}
}
5.定時任務和腳本任務
假設總經理比較忙,太長時間忘記審批,這個時候可以設定定時任務,調用腳本進行通知
定時任務設定
時間格式使用ISO-8601使用方式可以參考百度百科;其中循環時間可以使用corn表達式
腳本任務設定
腳本支援JavaScript, groovy,研究當中,使用JavaScript
腳本内容中我們可以調用java背景代碼中方法
如下callService是我們在java背景中寫的一個托管給spring的類,execution是activiti内置的對象,javascript和java代碼中都能對其進行調用,可以通過execution擷取該流程目前執行個體id,流程變量等。
@Component
public class CallService {
public String get(DelegateExecution execution){
System.out.println("----get----"+new Date()+"processInstanceId="+execution.getProcessInstanceId()+"--businessKey="+execution.getProcessBusinessKey());
return null;
}
}
6.内置定時啟動事件
應用場景:需要定時啟動某些流程的時候,我們可以使用定時啟動事件做為開始事件。
此時隻需要将此流程部署即可,注意點:如果需要使用該定時啟動事件的流程來定時啟動任務,則部署該定時啟動事件流程時需要設定不同流程名(processDefinitonKey)。
和前端探讨:1.修改節點内容
四.Activiti架構
activiti.cfg.xml
activiti 的引擎配置檔案,包括:ProcessEngineConfiguration 的定義、資料源定義、事務管理器等,此檔案其實就是一個 spring 配置檔案。
ProcessEngineConfiguration
流程引擎的配置類,通過 ProcessEngineConfiguration 可以建立工作流引擎 ProceccEngine。
ProcessEngine
工作流引擎,相當于一個門面接口,通過 ProcessEngineConfiguration 建立 processEngine,通過ProcessEngine 建立各個 service 接口。
7個service,在研究當中隻看
IdentityService, FormService,ManagementService暫無研究
RepositoryService
是 activiti 的資源管理類,提供了管理和控制流程釋出包和流程定義的操作。使用工作流模組化工具設計的業務流程圖需要使用此 service 将流程定義檔案的内容部署到計算機。
除了部署流程定義以外還可以:
查詢引擎中的釋出包和流程定義。
暫停或激活釋出包,對應全部和特定流程定義。 暫停意味着它們不能再執行任何操作了,激活
是對應的反向操作。
獲得多種資源,像是包含在釋出包裡的檔案, 或引擎自動生成的流程圖。
獲得流程定義的 pojo 版本, 可以用來通過 java 解析流程,而不必通過 xml。
RuntimeService
它是 activiti 的流程運作管理類。可以從這個服務類中擷取很多關于流程執行相關的資訊
TaskService
是 activiti 的任務管理類。可以從這個類中擷取任務的資訊。
HistoryService
是 activiti 的曆史管理類,可以查詢曆史資訊,執行流程時,引擎會儲存很多資料(根據配置),比
如流程執行個體啟動時間,任務的參與者, 完成任務的時間,每個流程執行個體的執行路徑,等等。 這個
服務主要通過查詢功能來獲得這些資料。