經過了長時間的學習和探索,對activiti的工作流有了初步的認識,也積累下了些許經驗分享給大家
不足之處以及建議歡迎指正~
開發環境:activiti5.22.0 springboot1.5.4
流程設計使用的是集成的activiti流程設計器
部署流程
/**
* 發佈模型爲流程實例
*/
@ApiOperation(value = "發佈模型爲流程定義")
@PostMapping("{id}/deployment")
public R deploy(@PathVariable("id") String id) throws Exception {
//獲取模型
RepositoryService repositoryService = processEngine.getRepositoryService();
Model modelData = repositoryService.getModel(id);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (bytes == null) {
return R.error("模型數據爲空,請先設計流程併成功保存,再進行發佈。");
}
JsonNode modelNode = new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
if (model.getProcesses().size() == 0) {
return R.error("數據模型不符要求,請至少設計一條主線流程。");
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
//發佈流程
String processName = modelData.getName() + ".bpmn20.xml";
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.name(modelData.getName())
.addString(processName, new String(bpmnBytes, "UTF-8"));
Deployment deployment = deploymentBuilder.deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);
return R.ok();
}
獲取工作流流程模型列表(帶分頁):
/**
* 獲取流程model列表(分頁)
*/
@RequestMapping(value = "/list", method = RequestMethod.POST)
public TableResultResponse<Model> list(@RequestParam Map<String, Object> params) {
int page = Integer.parseInt((String) params.get("page"));
int limit = Integer.parseInt((String) params.get("limit"));
Page<Object> result = PageHelper.startPage(page, limit);
List<Model> list = repositoryService.createModelQuery().orderByCreateTime().desc().list();
return new TableResultResponse<Model>(result.getTotal(), list);
}
刪除流程模型:
/**
* 刪除模型
*/
@DeleteMapping("{id}")
@ApiOperation(value = "刪除模型")
public Object deleteModel(@PathVariable("id") String id) {
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.deleteModel(id);//刪除模型
repositoryService.deleteDeployment(id, true);//如果存在運行中的流程,級聯刪除設置爲true
return R.ok();
}
工作流運行
public R startProcess() {
String processDefinitionKey = "獲取流程設計的key";
ProcessInstance instance = null;
//判斷是否存在流程部署
List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionKey)//根據流程定義的key查詢
.list();
if(list != null && list.size() > 0) {
//啓動流程實例(指定下級經辦人)
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("user", "獲取下級經辦人");
instance = processEngine.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey, variables);
} else {
//流程未部署,或其他情況
return R.ok("流程未部署,請檢查流程定義").put("code", 500);
}
if(instance != null) {
//流程啓動成功
System.out.println("流程實例id=" + instance.getProcessInstanceId());
System.out.println("流程實例name=" + instance.getName());
return R.ok().put("data", "流程啓動成功");
} else {
return R.ok("未獲取到流程實例,請檢查是否發佈!").put("code", 500);
}
}
流程啓動的時候,可以動態指定下級經辦人,或者不指定下級經辦人而在流程設計中設置好,直接啓動流程即可:
processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
流程刪除
/**
* 刪除流程實例
* @param processInstanceId
*/
@RequestMapping(value = "/deleteWf/{processInstanceId}", method = RequestMethod.DELETE)
public void delete(@PathVariable("processInstanceId") String processInstanceId){
runtimeService.deleteProcessInstance(processInstanceId, "刪除流程實例原因");
}
根據用戶獲取待辦任務列表,或任務個數(接口中的userID爲實際業務中assignee設置的爲人員id)
/**
* 根據用戶ID獲取用戶待辦任務個數
*/
public int taskCountByUserID(String userID) {
int count = count = count + taskService.createTaskQuery().taskAssignee(userID).list().size();
return count;
}
/**
* 根據用戶ID獲取用戶待辦任務列表
*/
public List<Task> taskList(String userID) {
//查詢個人任務列表
List<Task> taskList = taskService.createTaskQuery().taskAssignee(userID).list();
return taskList;
}
審批
@RequestMapping(value = "/complete/{taskID}", method = RequestMethod.GET)
@ApiOperation("審批通過,添加信息")
public R copmlete(@PathVariable("taskID") String taskID) {
//查詢是否有正在審批任務
Task task = taskService.createTaskQuery().taskId(taskID).singleResult();
if(task != null) {
//完成審批任務
taskService.complete(taskID);
//如果需要傳遞參數的話 task.getProcessInstanceId()獲取processInstanceId
//runtimeService.setVariable(processInstanceId, "變量名", 參數);全局變量
//taskService.setVariableLocal(taskID, "變量名", 參數);局部變量,該task下
//添加批註的方法
//taskService.addComment(taskID, processInstanceId, "批註信息");
}
return R.ok("審批成功");
}
駁回的流程設計需要節點的流轉,設置好條件進行判斷流轉方向
會籤(多實例)的設計,在該業務中設計的是多實例並行任務
將多實例任務設置爲Parallel並行,設置參數變量,可以通過監聽器將會籤人員集合傳遞進來,也可以在上級節點指定參數傳遞
public class CompleteListener implements TaskListener {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void notify(DelegateTask delegateTask) {
List<String> assigneeList = new ArrayList<String>();
assigneeList.add("部門一");
assigneeList.add("部門二");
delegateTask.setVariable("assigneeList", assigneeList);
}
}
添加監聽器設置會籤人員集合
歷史記錄表的應用:
act_hi_actinst:歷史節點信息表,審批節點的歷史記錄,可以獲取歷史活動節點的信息
act_hi_comment:歷史審批記錄表,可以獲取審批批註信息
act_hi_procinst:歷史流程實例表,可以獲取歷史流程實例的運行記錄如是否結束,開始時間,結束時間等
act_hi_taskinst:歷史任務信息表,可以獲取歷史任務的審批記錄信息,審批人,審批時間
act_hi_varinst:歷史流程變量表,可以獲取歷史流程實例下的流程變量信息,如存放的審批信息等
問題彙總
1. 獲取審批批註信息問題
開發過程中,添加審批批註成功,但是部署生成環境是CentOS,發現存在獲取亂碼的情況
//獲取批註信息
List<Comment> comments = processEngine.getTaskService()
.getTaskComments(historicActivityInstance.getTaskId());
Comment對象提供的api獲取的是FULL_MSG_字段的blob類型文件信息,存在亂碼現象,其中一種解決方式:
定義新的MyCommentEntity接收對象獲取message信息
List<MyCommentEntity> myCommentEntities = new ArrayList<MyCommentEntity>();
if(comments != null && comments.size() > 0) {
//創建我們自己的list集合
//爲每一個查詢到接口實現類複製屬性到我們自己的類中,解析爲前端JSON數據
for(Comment comment :comments){
//創建我們自己的類
MyCommentEntity myCommentEntity = new MyCommentEntity();
//屬性複製,源屬性爲commentEntity, 目標屬性爲myCommentEntity
BeanUtils.copyProperties(comment, myCommentEntity);
//添加我們自己的類
myCommentEntities.add(myCommentEntity);
}
//get批註信息即可
//list.get(0).getMessage();
}
MyCommentEntity實體類:
@Getter
@Setter
public class MyCommentEntity {
private String id;
private String userId;//用戶名,對應的是act_hi_comment表的USER_ID_字段
private Date date;
private String taskId;//任務id
private String processInstanceId;//流程定義id
private String message;//審批信息
private String fullMessage;
}