目前的項目主要有兩個審批流程,在審批過程中需要發送郵件給申請人告知目前進展,此處記錄下我在項目中是如何使用flowable工作流與業務相結合的。
1. 添加工作流依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<!-- spring aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-rest -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 郵件服務 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<!-- 日誌 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.flowable/flowable-spring-boot-starter-process -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-process</artifactId>
<version>6.4.0</version>
</dependency>
</dependencies>
2. 在application.yml中增加配置項
flowable:
check-process-definitions: false #設置需要手動部署工作流
3. 畫流程圖
設置審批候選人爲固定的某個色的所有人
實際應用中,除了需要將流程完整的結束,我們通常需要跟蹤業務狀態,通常每個處理節點都會對應一個業務狀態,此處指定方法負責更新狀態和發送郵件
4. 由於每個業務系統都會有自己的用戶角色權限管理,因此需要與flowable的用戶組關係保持同步,一種方法是利用監聽器,當業務系統編輯用戶信息時就同步至flowable用戶表中,另一種就是刪除flowable的用戶組關係表,利用視圖將業務系統的用戶組關係同步至flowable的用戶組關係表中,並且視圖名稱與原flowable用戶組關係表名稱相同
5. 代碼
###部署工作流###
@Transactional(readOnly = false)
public Object deploy (final String processName) {
logger.info("---- FlowService deploy begin ----");
final Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("processes/" + processName + ".bpmn")
.addClasspathResource("processes/" + processName + ".png")
.name(processName)
.key(processName)
.deploy();
final Map<String, Object> map = new HashMap<>();
map.put("deploymentId", deployment.getId());
map.put("deploymentKey", deployment.getKey());
map.put("deploymentName", deployment.getName());
map.put("deploymentEngineVersion", deployment.getEngineVersion());
logger.info("---- FlowService deploy end ----");
return map;
}
###查看已部署的工作流###
public Object deployedProcessList() {
logger.info("---- FlowService deployedProcess begin ----");
final List<Deployment> deploymentList = processEngine.getRepositoryService()
.createDeploymentQuery()
.orderByDeploymenTime()
.asc()
.list();
final List<Map<String, Object>> list = new ArrayList<>();
for (Deployment deployment : deploymentList) {
final Map<String, Object> map = new HashMap<>();
map.put("deploymentId", deployment.getId());
map.put("deploymentKey", deployment.getKey());
map.put("deploymentName", deployment.getName());
map.put("deploymentEngineVersion", deployment.getEngineVersion());
list.add(map);
}
logger.info("---- FlowService deployedProcess end ----");
return list;
}
/**
* 查詢流程定義
* @return
*/
public Object processDefinitionList () {
logger.info("---- FlowService getProcessDefinition begin ----");
final List<ProcessDefinition> definitionList = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.list();
final List<Map<String, Object>> list = new ArrayList<>();
for (ProcessDefinition processDefinition : definitionList) {
final Map<String, Object> map = new HashMap<>();
map.put("definitionId", processDefinition.getId());
map.put("definitionKey", processDefinition.getKey());
map.put("definitionName", processDefinition.getName());
map.put("definitionDeploymentId", processDefinition.getDeploymentId());
map.put("definitionResourceName", processDefinition.getResourceName());
map.put("definitionVersion", processDefinition.getVersion());
map.put("definitionEngineVersion", processDefinition.getEngineVersion());
list.add(map);
}
logger.info("---- FlowService getProcessDefinition end ----");
return list;
}
/**
* 啓動一個工作流
*
* @param processName 工作流模板 (啓動最新的版本)
* @param variables 參數表
* @param user 啓動人
* @return
*/
@Transactional(readOnly=false)
public String startProcess(String processName, String key, Map<String, Object> variables) {
IdentityService identityService = processEngine.getIdentityService();
identityService.setAuthenticatedUserId(UserUtils.getCurrentUser().getUserName());
logger.info("設置啓動人");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processName, key, variables);
return processInstance.getId();
}
/**
* 獲取當前角色待辦任務列表
* @return
*/
public Object getRoleTaskList() {
logger.info("---- FlowService getRoleTaskList begin ----");
List<Task> taskList = processEngine.getTaskService()
.createTaskQuery()
.taskCandidateGroup(UserUtils.getCurrentUser().getRoleName())
.orderByTaskCreateTime()
.asc()
.list();
final List<Map<String, Object>> list = new ArrayList<>();
for (Task task : taskList) {
final Map<String, Object> map = new HashMap<>();
map.put("taskId", task.getId());
map.put("createTime", task.getCreateTime());
map.put("taskName", task.getName());
map.put("taskOwner", task.getOwner());
map.put("processDefinitionId", task.getProcessDefinitionId());
map.put("processInstanceId", task.getProcessInstanceId());
map.put("taskDefinitionId", task.getTaskDefinitionId());
map.put("taskDefinitiionKey", task.getTaskDefinitionKey());
list.add(map);
}
logger.info("---- FlowService getRoleTaskList end ----");
return list;
}
/**
* 獲取當前用戶待辦任務列表
* @return
*/
public Object getPersonalTaskList() {
logger.info("---- FlowService getPersonalTaskList begin ----");
final List<Task> taskList = processEngine.getTaskService()
.createTaskQuery()
.taskAssignee(UserUtils.getCurrentUser().getUserName())
.orderByTaskCreateTime()
.asc()
.list();
final List<Map<String, Object>> list = new ArrayList<>();
for (Task task : taskList) {
final Map<String, Object> map = new HashMap<>();
map.put("taskId", task.getId());
map.put("createTime", task.getCreateTime());
map.put("taskName", task.getName());
map.put("taskOwner", task.getOwner());
map.put("processDefinitionId", task.getProcessDefinitionId());
map.put("processInstanceId", task.getProcessInstanceId());
map.put("taskDefinitionId", task.getTaskDefinitionId());
map.put("taskDefinitiionKey", task.getTaskDefinitionKey());
list.add(map);
}
logger.info("---- FlowService getPersonalTaskList end ----");
return list;
}
/**
* 判斷所處理的任務是否是當前用戶或當前用戶角色的任務
* @param taskId
* @return
*/
public boolean isPersonalTask (final String taskId) {
final String currentUserName = UserUtils.getCurrentUser().getUserName();
final Task personalTask = processEngine.getTaskService()
.createTaskQuery()
.taskAssignee(currentUserName)
.taskId(taskId)
.singleResult();
logger.info("current user name: " + currentUserName);
logger.info("taskId: " + taskId);
if (personalTask == null) {
logger.info("personalTask is null");
} else {
logger.info("personal taskId: " + personalTask.getId() + "personal assignee: " + personalTask.getAssignee());
}
if (personalTask != null && taskId.equals(personalTask.getId())) {
return true;
}
final String currentRoleName = UserUtils.getCurrentUser().getRoleName();
final Task roleTask = processEngine.getTaskService()
.createTaskQuery()
.taskCandidateGroup(currentRoleName)
.taskId(taskId)
.singleResult();
logger.info("taskId: " + taskId);
if (roleTask == null) {
logger.info("roleTask is null");
} else {
logger.info("role taskId: " + roleTask.getId() + "role assignee: " + roleTask.getAssignee());
}
if (roleTask != null && taskId.equals(taskId)) {
return true;
}
return false;
}
/**
* 獲取所有未處理的任務
* @return
*/
public Object getUnresolvedTaskList() {
List<Task> taskList = processEngine.getTaskService()
.createTaskQuery()
.orderByTaskCreateTime()
.asc()
.list();
final List<Map<String, Object>> list = new ArrayList<>();
for (Task task : taskList) {
final Map<String, Object> map = new HashMap<>();
map.put("taskId", task.getId());
map.put("createTime", task.getCreateTime());
map.put("taskName", task.getName());
map.put("taskOwner", task.getOwner());
map.put("processDefinitionId", task.getProcessDefinitionId());
map.put("processInstanceId", task.getProcessInstanceId());
map.put("taskDefinitionId", task.getTaskDefinitionId());
map.put("taskDefinitiionKey", task.getTaskDefinitionKey());
list.add(map);
}
return list;
}
/**
* 簽收任務
* @param taskId
* @param username
*/
@Transactional(readOnly = false)
public void claim(String taskId, String username) {
logger.info("簽收任務:"+ taskId + " 簽收人:" + username + " begin");
processEngine.getTaskService().claim(taskId,username);
logger.info("簽收任務:"+ taskId + " 簽收人:" + username + " end");
}
/**
* 執行某個流程節點
* @param taskId
* @param variables
*/
@Transactional(readOnly=false)
public void completeTask(String taskId, Map<String, Object> variables) {
if (!isPersonalTask(taskId)) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("請任務處理人或處理角色操作"));
}
processEngine.getTaskService().complete(taskId, variables);
logger.info("完成任務:" + taskId);
}
/**
* 執行某個流程節點, 待審批意見和附件
* @param taskId
* @param variables
* @param comment
* @param fileMap <文件路徑, 文件名稱>
*/
@Transactional(readOnly=false)
public void completeTask(final String taskId, final Map<String, Object> variables, final String action, String opinion, final Map<String, Object> fileMap) {
logger.info("task id: " + taskId + " ; action = " + action);
if (!isPersonalTask(taskId)) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("請任務處理人或處理角色操作"));
}
//添加批註時候的審覈人
Authentication.setAuthenticatedUserId(UserUtils.getCurrentUser().getUserName());
final TaskService taskService = processEngine.getTaskService();
final Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (StringUtils.isEmpty(opinion)) {
opinion = action;
} else {
opinion = action + ": " + opinion;
}
taskService.addComment(taskId, task.getProcessInstanceId(), opinion);
if (fileMap != null) {
final Iterator it = fileMap.keySet().iterator();
while(it.hasNext()) {
final String filePath = (String) it.next();
final String fileName = (String) fileMap.get(filePath);
String suffix = "";
if (fileName.contains(".") && !fileName.endsWith(".")) {
suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
} else {
if (filePath.contains(".") && !filePath.endsWith(".")) {
suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
}
}
taskService.createAttachment(suffix, taskId, task.getProcessInstanceId(), fileName, null, filePath);
}
}
try {
taskService.complete(taskId, variables);
} catch (Exception e) {
logger.error("處理任務失敗", e);
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("任務處理失敗"));
}
logger.info("完成任務:" + taskId);
}
/**
* 獲取審批歷史記錄
* @param processInstanceId 流程實例ID
* @return
*/
public List<ApprovalHistory> getApprovalHistory (final String processInstanceId) {
final List<ApprovalHistory> approvalHistoryList = new ArrayList<>();
//通過流程實例查詢所有的(用戶任務)歷史活動
List<HistoricActivityInstance> historicActivityInstanceList = processEngine.getHistoryService()
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.activityType("userTask")
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
final String historyTaskId = historicActivityInstance.getTaskId();
//每個節點所產生的文檔
final List<Attachment> attachments = processEngine.getTaskService().getTaskAttachments(historyTaskId);
final List<HistoryFile> historyFileList = new ArrayList<>();
for (Attachment attachment : attachments) {
final HistoryFile historyFile = new HistoryFile();
historyFile.setPath(attachment.getUrl());
historyFile.setName(attachment.getName());
historyFileList.add(historyFile);
}
//每個節點的評論
final List<Comment> comments = processEngine.getTaskService().getTaskComments(historyTaskId);
if (comments != null && comments.size() > 0) {
for (Comment comment : comments) {
final ApprovalHistory approvalHistory = new ApprovalHistory();
final User user = userDao.queryByUserName(comment.getUserId());
approvalHistory.setRoleName(user.getRoleName());
approvalHistory.setUserName(user.getName() + " (" + user.getUserName() + ")");
approvalHistory.setOperateTime(comment.getTime());
approvalHistory.setOpinion(comment.getFullMessage());
approvalHistory.setTaskId(historyTaskId);
approvalHistory.setProcessInstanceId(processInstanceId);
approvalHistory.setHistoryFileList(historyFileList);
approvalHistoryList.add(approvalHistory);
}
}
}
return approvalHistoryList;
}
public List<Comment> getProcessComments(String processInstanceId) {
final List<Comment> commentList = new ArrayList<>();
//通過流程實例查詢所有的(用戶任務)歷史活動
List<HistoricActivityInstance> historicActivityInstanceList = processEngine.getHistoryService()
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.activityType("userTask")
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
final String historyTaskId = historicActivityInstance.getTaskId();
List<Comment> comments = processEngine.getTaskService().getTaskComments(historyTaskId);
if (comments != null && comments.size() > 0) {
commentList.addAll(comments);
}
}
return commentList;
}
/**
* 生成流程進展圖
* @param processKey
* @param request
* @return
*/
public void genProcessDiagram(final String processInstanceId, final HttpServletResponse response) {
logger.info("---- FlowService genProcessDiagram begin ----");
final HistoryService historyService = processEngine.getHistoryService();
final RuntimeService runtimeService = processEngine.getRuntimeService();
//獲得當前活動的節點
String processDefinitionId = "";
if (isFinished(processInstanceId)) {
//如果流程已經結束,則得到結束節點
HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (hpi == null) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程定義不存在"));
}
processDefinitionId = hpi.getProcessDefinitionId();
} else {
//如果流程沒有結束,則取當前活動節點
//根據流程實例ID獲得當前處於活動狀態的activityId合集
final ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance == null) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程實例不存在"));
}
processDefinitionId = instance.getProcessDefinitionId();
}
final List<String> highLightedActivitis = new ArrayList<String>();
//獲得活動的節點
List<HistoricActivityInstance> highLightActivityList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
highLightActivityList = highLightActivityList.subList(highLightActivityList.size() - 1, highLightActivityList.size());
for (HistoricActivityInstance historicActivityInstance : highLightActivityList) {
final String activityId = historicActivityInstance.getActivityId();
//判斷節點是否在當前節點之前
highLightedActivitis.add(activityId);
}
//需要高亮顯示的線
final List<String> flows = new ArrayList<>();
final BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(processDefinitionId);
final ProcessEngineConfiguration config = processEngine.getProcessEngineConfiguration();
final ProcessDiagramGenerator diagramGenerator = config.getProcessDiagramGenerator();
final InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivitis, flows, config.getActivityFontName(),
config.getLabelFontName(), config.getAnnotationFontName(), config.getClassLoader(), 1.0, true);
OutputStream outputStream = null;
byte[] buf = new byte[1024];
int legth = 0;
try {
outputStream = response.getOutputStream();
while ((legth = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, legth);
}
outputStream.flush();
} catch (IOException e) {
logger.error("生成流程圖片失敗", e);
throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCEPTION.setExceptionMsg("生成流程圖片失敗"));
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
logger.error("輸出流關閉失敗", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
logger.error("輸入流關閉失敗", e);
}
}
}
logger.info("---- FlowService genProcessDiagram end ----");
}
/**
* 判斷節點是否結束
* @param processInstanceId
* @return
*/
public boolean isFinished(final String processInstanceId) {
return processEngine.getHistoryService().createHistoricProcessInstanceQuery().finished().processInstanceId(processInstanceId).count() > 0;
}
/**
* 查看流程定義圖
* @param deploymentId
* @param response
*/
public void viewDefinitionDiagram(final String deploymentId, final HttpServletResponse response) {
final RepositoryService repositoryService = processEngine.getRepositoryService();
final ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
if (processDefinition == null) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程定義不存在"));
}
InputStream inputStream = processEngine.getRepositoryService().getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
OutputStream outputStream = null;
byte[] buf = new byte[1024];
int legth = 0;
try {
outputStream = response.getOutputStream();
while ((legth = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, legth);
}
outputStream.flush();
} catch (IOException e) {
logger.error("獲取流程定義圖片失敗", e);
throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCEPTION.setExceptionMsg("獲取流程定義圖片失敗"));
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
logger.error("輸出流關閉失敗", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
logger.error("輸入流關閉失敗", e);
}
}
}
}
/**
* 根據 processInstanceId 獲取當前的任務
* @param processInstanceId
* @return
*/
public Task findTaskByProcessInstanceId(String processInstanceId) {
final Task task = processEngine.getTaskService()
.createTaskQuery()
.processInstanceId(processInstanceId)
.singleResult();
return task;
}
/**
* 撤回,返回 taskID
* @param processInstanceId
* @return
*/
public Object withdraw(String processInstanceId) {
// final ProcessInstance processInstance = processEngine.getRuntimeService()
// .createProcessInstanceQuery()
// .processInstanceId(processInstanceId)
// .singleResult();
final TaskService taskService = processEngine.getTaskService();
final HistoryService historyService = processEngine.getHistoryService();
final RepositoryService repositoryService = processEngine.getRepositoryService();
final RuntimeService runtimeService = processEngine.getRuntimeService();
final String currentUserName = UserUtils.getCurrentUser().getUserName();
final Task task = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (task == null) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程未啓動或已執行完成,無法撤回"));
}
List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.orderByTaskCreateTime()
.asc()
.list();
HistoricTaskInstance myTask = null;
for (HistoricTaskInstance historicTaskInstance : htiList) {
if(currentUserName.equals(historicTaskInstance.getAssignee())) {
myTask = historicTaskInstance;
break;
}
}
if(myTask.getId() == null) {
throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("該任務非當前用戶提交,無法撤回"));
}
final String processDefinitionId = myTask.getProcessDefinitionId();
final ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.processDefinitionId(processDefinitionId)
.singleResult();
final BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//變量
Map<String, VariableInstance> variables = runtimeService.getVariableInstances(task.getExecutionId());
String myActivityId = null;
final List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
.executionId(myTask.getExecutionId()).finished().list();
for(HistoricActivityInstance hai : haiList) {
if(myTask.getId().equals(hai.getTaskId())) {
myActivityId = hai.getActivityId();
break;
}
}
FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
logger.warn("------->> activityId:" + activityId);
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
//記錄原活動方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
//清理活動方向
flowNode.getOutgoingFlows().clear();
//建立新方向
List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId");
newSequenceFlow.setSourceFlowElement(flowNode);
newSequenceFlow.setTargetFlowElement(myFlowNode);
newSequenceFlowList.add(newSequenceFlow);
flowNode.setOutgoingFlows(newSequenceFlowList);
Authentication.setAuthenticatedUserId(UserUtils.getCurrentUser().getUserName());
taskService.addComment(task.getId(), task.getProcessInstanceId(), "撤回");
Map<String,Object> currentVariables = new HashMap<String,Object>();
currentVariables.put("applier", currentUserName);
//完成任務
taskService.complete(task.getId(),currentVariables);
//恢復原方向
flowNode.setOutgoingFlows(oriSequenceFlows);
return task.getId();
}
###更新流程節點狀態和發送郵件###
public void updateStatus (final DelegateExecution execution, final String status) {
String businessKey = execution.getProcessInstanceBusinessKey();
//根據業務id自行處理業務表
System.out.println("業務表["+businessKey+"]狀態更改成功,狀態更改爲:" + status + ", 流程實例ID:" + execution.getProcessInstanceId());
if (businessKey.contains(":")) {
final Integer designId = Integer.valueOf(businessKey.split(":")[1]);
final Design design = (Design) designDao.queryById(designId);
design.setStatus(status);
designDao.update(design);
if (design.getCreateUserId().equals(UserUtils.getCurrentUser().getId())) {
return;
}
//根據流程關鍵字和狀態查找郵件模板
MailTemplate mailTemplate = mailTemplateDao.findByProcessKeyAndStatus(Constant.PROCESS_KEY_DESIGN , status);
if (mailTemplate == null) {
mailTemplate = new MailTemplate();
mailTemplate.setContent("郵件通知");
mailTemplate.setSubject("郵件通知");
}
String content = mailTemplate.getContent();
if (!StringUtils.isEmpty(content)) {
content = content.replaceAll("\\$\\{name\\}", design.getName());
}
final User user = (User) userDao.queryById(design.getCreateUserId());
mailService.sendMail(user.getEmail(), mailTemplate.getSubject(), content, execution.getProcessInstanceId());
}
}