srpign boot + activiti7 + 在线编辑器整合
先看效果



参考地址:https://blog.csdn.net/huashenghn/article/details/103088775
1.导入静态资源 diagram-viewer、editor-app
2.配置 editor-app 的 app-cfg.js 中的 contextRoot
3.新增编辑流程所需要的resource
ModelEditorJsonRestResource.java
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ***.***.activiti.resource;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @author
*/
@RestController
@RequestMapping("/service")
@Api(value = "aciviti-app model editor json", tags = {"保存模型"})
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private ObjectMapper objectMapper;
@RequestMapping(value="/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
public ObjectNode getEditorJson(@PathVariable String modelId) {
ObjectNode modelNode = null;
Model model = repositoryService.getModel(modelId);
if (model != null) {
try {
if (StringUtils.isNotEmpty(model.getMetaInfo())) {
modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
} else {
modelNode = objectMapper.createObjectNode();
modelNode.put(MODEL_NAME, model.getName());
}
modelNode.put(MODEL_ID, model.getId());
ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(
new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
modelNode.put("model", editorJsonNode);
} catch (Exception e) {
LOGGER.error("Error creating model JSON", e);
throw new ActivitiException("Error creating model JSON", e);
}
}
return modelNode;
}
}
ModelSaveRestResource.java
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ***.***.activiti.resource;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
/**
* @author
*/
@RestController
@RequestMapping("/service")
@Api(value = "aciviti-app model", tags = {"保存模型"})
public class ModelSaveRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private ObjectMapper objectMapper;
@RequestMapping(value="/model/{modelId}/save", method = RequestMethod.PUT)
@ResponseStatus(value = HttpStatus.OK)
public void saveModel(@PathVariable String modelId,HttpServletRequest request) {
String name =request.getParameter("name");
String description =request.getParameter("description");
String json_xml =request.getParameter("json_xml");
String svg_xml =request.getParameter("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);
}
}
}
StencilsetRestResource.java
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ***.***.activiti.resource;
import io.swagger.annotations.Api;
import org.activiti.engine.ActivitiException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.*;
import java.io.InputStream;
/**
* @author
*/
@RestController
@RequestMapping("/service")
@Api(value = "aciviti-app stencilset", tags = {"获取 stencilset.json"})
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
public class StencilsetRestResource {
@RequestMapping(value="/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
public @ResponseBody String getStencilset() {
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
try {
return IOUtils.toString(stencilsetStream, "utf-8");
} catch (Exception e) {
throw new ActivitiException("Error while loading stencil set", e);
}
}
}
4.新增维护模型、流程的接口
SimpleUserTaskApiController.java
package ***.***.activiti7.controller;
import static ***.***.constant.AllocationConstant.APPLICATION_JSON_UTF8;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Resource;
import org.activiti.api.task.model.builders.CompleteTaskPayloadBuilder;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import ***.***.activiti7.bean.AssigneeVO;
import ***.***.activiti7.bean.BackReq;
import ***.***.activiti7.bean.BackRsp;
import ***.***.activiti7.bean.BatchBackReq;
import ***.***.activiti7.bean.BatchBackRsp;
import ***.***.activiti7.bean.BatchComplateReq;
import ***.***.activiti7.bean.BatchComplateRsp;
import ***.***.activiti7.bean.BatchStartReq;
import ***.***.activiti7.bean.BatchStartRsp;
import ***.***.activiti7.bean.BatchStopReq;
import ***.***.activiti7.bean.BatchStopRsp;
import ***.***.activiti7.bean.ClaimReq;
import ***.***.activiti7.bean.ClaimRsp;
import ***.***.activiti7.bean.ComplateReq;
import ***.***.activiti7.bean.ComplateRsp;
import ***.***.activiti7.bean.DiagramReq;
import ***.***.activiti7.bean.DiagramRsp;
import ***.***.activiti7.bean.GetInstanceReq;
import ***.***.activiti7.bean.GetInstanceRsp;
import ***.***.activiti7.bean.GetReq;
import ***.***.activiti7.bean.GetRsp;
import ***.***.activiti7.bean.StartReq;
import ***.***.activiti7.bean.StartRsp;
import ***.***.activiti7.bean.StopReq;
import ***.***.activiti7.bean.StopRsp;
import ***.***.activiti7.listeners.ProcessListener;
import ***.***.activiti7.mapper.CommActivityMapper;
import ***.***.activiti7.util.ActivitiUtils;
import ***.***.intf.service.CallService;
import ***.***.security.SecurityUtils;
import ***.***.system.exception.MyExceptionEnum;
import ***.***.user.mapper.UserMapper;
import ***.***.util.Assert;
import lombok.extern.slf4j.Slf4j;
import net.platform.center.exception.BusinessException;
@Slf4j
@RestController
@RequestMapping(path = "/task/", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
public class SimpleUserTaskApiController {
// #region 属性注入
private String consUsername = "username";
/**
* 流程定义和部署相关的存储服务
*/
@Autowired
private RepositoryService repositoryService;
/**
* 流程运行时相关的服务
*/
@Resource
private RuntimeService runtimeService;
/**
* 节点任务相关操作接口
*/
@Resource
private TaskService taskService;
@Resource
private TaskRuntime taskRuntime;
/**
* 历史记录相关服务接口
*/
@Resource
private HistoryService historyService;
@Autowired
private SecurityUtils securityUtils;
@Autowired
private CommActivityMapper commActivityMapper;
@Autowired
private CallService callService;
@Autowired
private UserMapper userMapper;
// #endregion
/**
* 启动流程实例
*
* @param req
* @return
*/
@PostMapping(path = "/start", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public StartRsp start(@RequestBody StartReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
Assert.notNull(req.getBody().getDeploymentKey(), MyExceptionEnum.INVALID_PARAMETER);
Assert.notNull(req.getBody().getBusinessKey(), MyExceptionEnum.INVALID_PARAMETER);
ProcessListener tempProcessListener =
getProcessListenerByKey(req.getBody().getDeploymentKey(), req.getBody().getBusinessKey());
Assert.notNull(tempProcessListener, MyExceptionEnum.NULL_ACT_PROCESS_MAPPING);
Assert.notNull(tempProcessListener.getCommActivity(), MyExceptionEnum.NULL_ACT_PROCESS_MAPPING);
tempProcessListener.getCommActivity();
tempProcessListener.setBusinessKey(req.getBody().getBusinessKey());
if (!tempProcessListener.checkCanStart()) {
throw new BusinessException(MyExceptionEnum.INVALID_ACT_PROCESS_STATE);
}
String username = req.getHeader().get(consUsername);
securityUtils.logInAs(username);
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(tempProcessListener.getCommActivity().getDeploymentId())
.singleResult();
Assert.notNull(processDefinition, MyExceptionEnum.NULL_ACT_PROCESS_DEFINITION);
ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinition.getId(),
req.getBody().getBusinessKey(), resetVariables(req.getBody().getVariables()));
// org.activiti.engine.task.Task tempTask = taskService.createTaskQuery()
// .processInstanceId(instance.getId())
// .orderByTaskCreateTime()
// .desc()
// .singleResult();
runtimeService.setProcessInstanceName(instance.getId(), req.getBody().getName());
// 获取表单属性
org.activiti.engine.task.Task task = taskService.createTaskQuery()
.processInstanceId(instance.getId())
.orderByTaskCreateTime()
.desc()
.singleResult();
// #TODO 待确认是否需要此步骤
// 是否是没有具体指派人的时候,才需要 setAssignee
// taskService.setAssignee(task.getId(),username);
StartRsp rsp = StartRsp.builder()
.body(StartRsp.StartRspBody.builder()
.taskId(task.getId())
.processInstanceId(instance.getId())
.businessKey(req.getBody().getBusinessKey())
.build())
.build();
return rsp;
}
@PostMapping(path = "/batchStart", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public BatchStartRsp batchStart(@RequestBody BatchStartReq req) {
BatchStartRsp rsp = new BatchStartRsp();
BatchStartReq.BatchStartReqBody body = req.getBody();
for (String businessKey : body.getBusinessKeys()) {
StartReq tempReq = StartReq.builder()
.body(StartReq.StartReqBody.builder()
.businessKey(businessKey)
.deploymentKey(body.getDeploymentKey())
.name(body.getName())
.variables(body.getVariables())
.build())
.build();
tempReq.setHeader(req.getHeader());
try {
StartRsp tempRsp = start(tempReq);
rsp.getBody().add(tempRsp.getBody());
} catch (Exception ex) {
rsp.getBody().add(StartRsp.StartRspBody.builder().businessKey(businessKey).build());
log.error("循环 start 异常", ex);
}
}
return rsp;
}
private HashMap<String, Object> resetVariables(HashMap<String, Object> variables) {
HashMap<String, Object> newVariables = new HashMap<>();
for (Map.Entry<String, Object> entry : variables.entrySet()) {
String key = entry.getKey().replace("-", "_");
newVariables.put(key, entry.getValue());
}
return newVariables;
}
/**
* 根据流程部署Id获取流程信息
*
* @param req
* @return
*/
@PostMapping(path = "/get", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public GetRsp get(@RequestBody GetReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
ProcessListener tempProcessListener = getProcessListenerByKey(req.getBody().getDeploymentKey(), null);
Assert.notNull(tempProcessListener, MyExceptionEnum.NULL_ACT_PROCESS_MAPPING);
Assert.notNull(tempProcessListener.getCommActivity(), MyExceptionEnum.NULL_ACT_PROCESS_MAPPING);
Deployment deployment = repositoryService.createDeploymentQuery()
.deploymentId(tempProcessListener.getCommActivity().getDeploymentId())
.singleResult();
Assert.notNull(deployment, MyExceptionEnum.NULL_ACT_PROCESS_DEFINITION);
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(tempProcessListener.getCommActivity().getDeploymentId())
.singleResult();
Assert.notNull(req, MyExceptionEnum.NULL_ACT_PROCESS_DEFINITION);
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
Assert.notNull(req, MyExceptionEnum.NULL_ACT_BPMN_MODEL);
List<UserTask> allUserTasks = ActivitiUtils.getAllUserTasks(bpmnModel);
Assert.notNull(allUserTasks, MyExceptionEnum.NULL_ACT_USER_TASK_DEFINITION);
GetRsp rsp = GetRsp.builder()
.body(GetRsp.GetRspBody.builder()
.tasks(new ArrayList<>())
.formProperties(new ArrayList<>())
.deploymentId(deployment.getId())
.deploymentName(deployment.getName())
.build())
.build();
// 设置第一环节审批表单格式
UserTask firstUserTask = allUserTasks.get(0);
rsp.getBody().setFormProperties(firstUserTask.getFormProperties());
for (UserTask userTask : allUserTasks) {
GetRsp.Task tempTask = GetRsp.Task.builder().id(userTask.getId()).name(userTask.getName()).build();
if (!CollectionUtils.isEmpty(userTask.getCandidateGroups())) {
tempTask.setCandidateGroups(userTask.getCandidateGroups());
} else if (!CollectionUtils.isEmpty(userTask.getCandidateUsers())) {
// region 设置候选人
for (String candidateUserName : userTask.getCandidateUsers()) {
log.trace("模拟查询用户user,待实现");
String name = userMapper.getNameByUserName(candidateUserName);
if (!StringUtils.isEmpty(name)) {
AssigneeVO candidateAssignee =
AssigneeVO.builder().username(candidateUserName).name(name).build();
tempTask.getCandidateUsers().add(candidateAssignee);
}
}
// endregion
} else if (!StringUtils.isEmpty(userTask.getAssignee()) && !ActivitiUtils.isEl(userTask.getAssignee())) {
String name = userMapper.getNameByUserName(userTask.getAssignee());
if (!StringUtils.isEmpty(name)) {
AssigneeVO assigneeVO = AssigneeVO.builder().username(userTask.getAssignee()).name(name).build();
tempTask.setAssignee(assigneeVO);
}
}
rsp.getBody().getTasks().add(tempTask);
}
// String url = String.format(tempProcessListener.getCommActivity().getFormUrl(),
// req.getBody().getBusinessKey());
// rsp.getBody().setFormUrl(url);
return rsp;
}
/**
* 签收
*
* @param req
* @return
*/
@PostMapping(path = "/claim", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public ClaimRsp claim(@RequestBody ClaimReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
String username = req.getHeader().get(consUsername);
securityUtils.logInAs(username);
org.activiti.engine.task.Task task =
taskService.createTaskQuery().taskId(req.getBody().getTaskId()).singleResult();
Assert.notNull(task, MyExceptionEnum.NULL_ACT_USER_TASK);
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(req.getBody().getTaskId()).build());
return ClaimRsp.builder().body(ClaimRsp.ClaimRspBody.builder().success(true).build()).build();
}
/**
* 驳回
*
* @param req
* @return
*/
@PostMapping(path = "/back", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public BackRsp back(@RequestBody BackReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
org.activiti.engine.task.Task task =
taskService.createTaskQuery().taskId(req.getBody().getTaskId()).singleResult();
Assert.notNull(task, MyExceptionEnum.NULL_ACT_USER_TASK);
String username = req.getHeader().get(consUsername);
if (!task.getAssignee().equals(username)) {
throw new BusinessException(MyExceptionEnum.INVALID_PERMISSION);
}
securityUtils.logInAs(username);
String processInstanceId = task.getProcessInstanceId();
// 取得所有历史任务按时间降序排序
List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.orderByTaskCreateTime()
.desc()
.list();
if (ObjectUtils.isEmpty(htiList) || htiList.size() < 2) {
throw new BusinessException(MyExceptionEnum.ERR_ACT_CAT_NOT_BACK);
}
// list里的第二条代表上一个任务
HistoricTaskInstance lastTask = htiList.get(1);
// list里第二条代表当前任务
HistoricTaskInstance curTask = htiList.get(0);
// 当前节点的executionId
String curExecutionId = curTask.getExecutionId();
// 上个节点的taskId
String lastTaskId = lastTask.getId();
// 上个节点的executionId
String lastExecutionId = lastTask.getExecutionId();
if (StringUtils.isEmpty(lastTaskId)) {
throw new BusinessException(MyExceptionEnum.ERR_ACT_CAT_NOT_BACK);
}
String processDefinitionId = lastTask.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
String lastActivityId = null;
List<HistoricActivityInstance> haiFinishedList =
historyService.createHistoricActivityInstanceQuery().executionId(lastExecutionId).finished().list();
for (HistoricActivityInstance hai : haiFinishedList) {
if (lastTaskId.equals(hai.getTaskId())) {
// 得到ActivityId,只有HistoricActivityInstance对象里才有此方法
// lastActivityId = hai.getActivityId();
break;
}
}
// 取得当前节点的信息
Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
String curActivityId = execution.getActivityId();
FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);
SequenceFlow targetSequenceFlow = curFlowNode.getIncomingFlows().get(0);
FlowNode targetFlowNode = (FlowNode) curFlowNode.getIncomingFlows().get(0).getSourceFlowElement();
FlowNode sourceFlowNode = (FlowNode) targetSequenceFlow.getSourceFlowElement();
// 记录当前节点的原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());
// 清理活动方向
curFlowNode.getOutgoingFlows().clear();
// 建立新方向
List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("nid_" + UUID.randomUUID().toString().replace("-", "_"));
newSequenceFlow.setSourceFlowElement(sourceFlowNode);
newSequenceFlow.setTargetFlowElement(targetFlowNode);
newSequenceFlowList.add(newSequenceFlow);
curFlowNode.setOutgoingFlows(newSequenceFlowList);
// 完成任务
CompleteTaskPayloadBuilder completeTaskPayloadBuilder = TaskPayloadBuilder.complete().withTaskId(task.getId());
// 每个环节对应的审批状态,是独立的
taskService.addComment(task.getId(), task.getProcessInstanceId(), ActivitiUtils.getCommentKey(),
req.getBody().getComment());
taskService.addComment(task.getId(), task.getProcessInstanceId(), ActivitiUtils.getApproveKey(),
String.valueOf(ActivitiUtils.APPROVE_BACK));
taskRuntime.complete(completeTaskPayloadBuilder.build());
// 恢复原方向
curFlowNode.setOutgoingFlows(oriSequenceFlows);
org.activiti.engine.task.Task nextTask =
taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
// 设置执行人
if (nextTask != null) {
taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
}
return BackRsp.builder().body(BackRsp.BackRspBody.builder().success(true).build()).build();
}
@PostMapping(path = "/batchBack", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public BatchBackRsp batchBack(@RequestBody BatchBackReq req) {
BatchBackRsp rsp = BatchBackRsp.builder().build();
for (BatchBackReq.BatchBackBody backReqBody : req.getBody()) {
org.activiti.engine.task.Task task =
taskService.createTaskQuery().processInstanceId(backReqBody.getInstanceId()).singleResult();
if (task == null) {
rsp.getBody()
.add(BatchBackRsp.BatchBackRspBody.builder()
.success(false)
.instanceId(backReqBody.getInstanceId())
.build());
log.info("流程实例 {} 获取不到 task", backReqBody.getInstanceId());
continue;
}
BackReq tempReq = BackReq.builder()
.body(BackReq.BackReqBody.builder().taskId(task.getId()).comment(backReqBody.getComment()).build())
.build();
tempReq.setHeader(req.getHeader());
try {
BackRsp tempRsp = back(tempReq);
rsp.getBody()
.add(BatchBackRsp.BatchBackRspBody.builder()
.success(tempRsp.getBody().isSuccess())
.instanceId(backReqBody.getInstanceId())
.build());
} catch (Exception ex) {
rsp.getBody()
.add(BatchBackRsp.BatchBackRspBody.builder()
.success(false)
.instanceId(backReqBody.getInstanceId())
.build());
log.error("循环 complete 异常", ex);
}
}
return rsp;
}
/**
* 終止
*
* @param req
* @return
*/
@PostMapping(path = "/stop", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public StopRsp stop(@RequestBody StopReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
org.activiti.engine.task.Task task =
taskService.createTaskQuery().processInstanceId(req.getBody().getProcessInstanceId()).singleResult();
Assert.notNull(task, MyExceptionEnum.NULL_ACT_USER_TASK);
// String username = req.getHeader().get(consUsername);
//
// if (!task.getAssignee().equals(username)) {
// throw new BusinessException(MyExceptionEnum.INVALID_PERMISSION);
// }
String username = task.getAssignee();
if (StringUtils.isEmpty(username)) {
Map<String, Object> variables = taskService.getVariables(task.getId());
String assigneeKey = ActivitiUtils.getAssigneeKey(task.getTaskDefinitionKey());
if (StringUtils.isEmpty(task.getAssignee()) && variables.containsKey(assigneeKey)) {
username = variables.get(assigneeKey).toString();
}
}
securityUtils.logInAs(username);
String processInstanceId = task.getProcessInstanceId();
// 取得所有历史任务按时间降序排序
List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.orderByTaskCreateTime()
.desc()
.list();
// list里第一条代表当前任务
HistoricTaskInstance curTask = htiList.get(0);
// 当前节点的executionId
String curExecutionId = curTask.getExecutionId();
String processDefinitionId = curTask.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 获取结束的节点信息
FlowNode endFlowNode = (FlowNode) ActivitiUtils.getEndEventFlowElement(bpmnModel);
// 取得当前节点的信息
Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
String curActivityId = execution.getActivityId();
FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);
// 记录当前节点的原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());
// 清理活动方向
curFlowNode.getOutgoingFlows().clear();
// 建立新方向
List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId");
newSequenceFlow.setSourceFlowElement(curFlowNode);
newSequenceFlow.setTargetFlowElement(endFlowNode);
newSequenceFlowList.add(newSequenceFlow);
curFlowNode.setOutgoingFlows(newSequenceFlowList);
// 完成任务
CompleteTaskPayloadBuilder completeTaskPayloadBuilder = TaskPayloadBuilder.complete()
.withVariable(ActivitiUtils.getApproveKey(), ActivitiUtils.APPROVE_END)
.withTaskId(task.getId());
taskRuntime.complete(completeTaskPayloadBuilder.build());
// 恢复原方向
curFlowNode.setOutgoingFlows(oriSequenceFlows);
return StopRsp.builder().body(StopRsp.StopRspBody.builder().success(true).build()).build();
}
@PostMapping(path = "/batchStop", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public BatchStopRsp batchStop(@RequestBody BatchStopReq req) {
BatchStopRsp rsp = BatchStopRsp.builder().build();
for (StopReq.StopReqBody stopReqBody : req.getBody()) {
StopReq tempReq = StopReq.builder().body(stopReqBody).build();
tempReq.setHeader(req.getHeader());
try {
StopRsp tempRsp = stop(tempReq);
rsp.getBody()
.add(BatchStopRsp.BatchStopRspBody.builder()
.success(tempRsp.getBody().isSuccess())
.processInstanceId(stopReqBody.getProcessInstanceId())
.build());
} catch (Exception ex) {
rsp.getBody()
.add(BatchStopRsp.BatchStopRspBody.builder()
.success(false)
.processInstanceId(stopReqBody.getProcessInstanceId())
.build());
log.error("循环 stop 异常", ex);
}
}
return rsp;
}
/**
* 处理环节
*
* @param req
* @return
*/
@PostMapping(path = "/batchComplete", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public BatchComplateRsp batchComplete(@RequestBody BatchComplateReq req) {
BatchComplateRsp rsp = BatchComplateRsp.builder().build();
for (BatchComplateReq.BatchComplateReqBody complateReqBody : req.getBody()) {
org.activiti.engine.task.Task task =
taskService.createTaskQuery().processInstanceId(complateReqBody.getInstanceId()).singleResult();
if (task == null) {
rsp.getBody()
.add(BatchComplateRsp.BatchComplateRspBody.builder()
.success(false)
.instanceId(complateReqBody.getInstanceId())
.build());
log.info("流程实例 {} 获取不到 task", complateReqBody.getInstanceId());
continue;
}
ComplateReq tempReq = ComplateReq.builder()
.body(ComplateReq.ComplateReqBody.builder()
.taskId(task.getId())
.comment(complateReqBody.getComment())
.approve(complateReqBody.getApprove())
.build())
.build();
tempReq.setHeader(req.getHeader());
try {
ComplateRsp tempRsp = complete(tempReq);
rsp.getBody()
.add(BatchComplateRsp.BatchComplateRspBody.builder()
.success(tempRsp.getBody().isSuccess())
.instanceId(complateReqBody.getInstanceId())
.build());
} catch (Exception ex) {
rsp.getBody()
.add(BatchComplateRsp.BatchComplateRspBody.builder()
.success(false)
.instanceId(complateReqBody.getInstanceId())
.build());
log.error("循环 complete 异常", ex);
}
}
return rsp;
}
/**
* 处理环节
*
* @param req
* @return
*/
@PostMapping(path = "/complete", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public ComplateRsp complete(@RequestBody ComplateReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
String username = req.getHeader().get(consUsername);
securityUtils.logInAs(username);
// TaskImpl task = (TaskImpl)taskRuntime.task(req.getBody().getTaskId());
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(req.getBody().getTaskId()).singleResult();
Assert.notNull(task, MyExceptionEnum.NULL_ACT_USER_TASK);
Map<String, Object> variables = taskService.getVariables(task.getId());
String assigneeKey = ActivitiUtils.getAssigneeKey(task.getTaskDefinitionKey());
if (StringUtils.isEmpty(task.getAssignee()) && variables.containsKey(assigneeKey)) {
task.setAssignee(variables.get(assigneeKey).toString());
taskService.setAssignee(task.getId(), variables.get(assigneeKey).toString());
// taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(req.getBody().getTaskId()).build());
}
if (!username.equals(task.getAssignee())) {
throw new BusinessException(MyExceptionEnum.INVALID_PERMISSION);
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
Assert.notNull(bpmnModel, MyExceptionEnum.NULL_ACT_BPMN_MODEL);
CompleteTaskPayloadBuilder completeTaskPayloadBuilder =
TaskPayloadBuilder.complete().withTaskId(req.getBody().getTaskId());
// region 表单数据处理
UserTask userTask = (UserTask) bpmnModel.getFlowElement(task.getTaskDefinitionKey());
if (userTask.getFormProperties().size() > 0) {
if (!CollectionUtils.isEmpty(req.getBody().getVariables())) {
completeTaskPayloadBuilder =
completeTaskPayloadBuilder.withVariable(ActivitiUtils.getFormsKey(), req.getBody().getVariables());
}
}
// endregion
// region 审批意见处理
if (ActivitiUtils.APPROVE_UN_KNOW != req.getBody().getApprove()) {
// 此处审批状态和下面审批状态作用不一样,主要给流程的el条件判断使用
completeTaskPayloadBuilder =
completeTaskPayloadBuilder.withVariable(ActivitiUtils.getApproveKey(), req.getBody().getApprove());
if (!StringUtils.isEmpty(req.getBody().getComment())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), ActivitiUtils.getCommentKey(),
req.getBody().getComment());
}
// 每个环节对应的审批状态,是独立的
taskService.addComment(task.getId(), task.getProcessInstanceId(), ActivitiUtils.getApproveKey(),
String.valueOf(req.getBody().getApprove()));
}
// endregion
// #TODO 需要看看是否可以将这个写在审批意见处理上面
taskRuntime.complete(completeTaskPayloadBuilder.build());
// 不同意时,退回到第一步可能没指派人时处理逻辑
org.activiti.engine.task.Task newTask =
taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
if (ActivitiUtils.APPROVE_UN_PASS == req.getBody().getApprove() && StringUtils.isEmpty(newTask.getAssignee())) {
org.activiti.engine.task.Task task1 = taskService.createTaskQuery().taskId(newTask.getId()).singleResult();
String assignees = taskService.getVariable(task1.getId(),
ActivitiUtils.getAssigneeKey(task.getTaskDefinitionKey()), String.class);
if (!StringUtils.isEmpty(assignees)) {
taskService.setAssignee(task1.getId(), assignees);
}
}
return ComplateRsp.builder().body(ComplateRsp.ComplateRspBody.builder().success(true).build()).build();
}
/**
* 画流程图
*
* @param req
* @return
* @throws IOException
*/
@PostMapping(path = "/diagram", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public DiagramRsp diagram(@RequestBody DiagramReq req) throws IOException {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
String processDefinitionId = null;
if (!StringUtils.isEmpty(req.getBody().getDeploymentId())) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(req.getBody().getDeploymentId())
.singleResult();
Assert.notNull(processDefinition, MyExceptionEnum.NULL_ACT_PROCESS_DEFINITION);
processDefinitionId = processDefinition.getId();
} else {
org.activiti.engine.task.Task task =
taskService.createTaskQuery().processInstanceId(req.getBody().getProcessInstanceId()).singleResult();
Assert.notNull(task, MyExceptionEnum.NULL_ACT_PROCESS_INSTANCE);
processDefinitionId = task.getProcessDefinitionId();
}
Assert.notNull(processDefinitionId, MyExceptionEnum.NULL_ACT_PROCESS_DEFINITION);
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
Assert.notNull(processDefinitionId, MyExceptionEnum.NULL_ACT_BPMN_MODEL);
List<HistoricActivityInstance> historicActivityInstanceList = null;
if (!StringUtils.isEmpty(req.getBody().getProcessInstanceId())) {
// 构造历史流程查询
HistoricActivityInstanceQuery historyInstanceQuery = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(req.getBody().getProcessInstanceId());
// 查询历史节点
historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
}
InputStream fileOssRecordInputStream = null;
try {
fileOssRecordInputStream = ActivitiUtils.getProcessDiagram(bpmnModel, historicActivityInstanceList);
if (fileOssRecordInputStream != null) {
String content = IOUtils.toString(fileOssRecordInputStream, StandardCharsets.UTF_8);
return DiagramRsp.builder().body(DiagramRsp.DiagramRspBody.builder().content(content).build()).build();
} else {
throw new BusinessException(MyExceptionEnum.ERR_OPT_FAIL);
}
} finally {
if (fileOssRecordInputStream != null) {
fileOssRecordInputStream.close();
}
}
}
/**
* 查看流程实例信息
*
* @param req
* @return
*/
@PostMapping(path = "/getInstance", consumes = APPLICATION_JSON_UTF8, produces = APPLICATION_JSON_UTF8)
@ResponseBody
public GetInstanceRsp getInstance(@RequestBody GetInstanceReq req) {
Assert.notNull(req, MyExceptionEnum.INVALID_PARAMETER);
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(req.getBody().getProcessInstanceId())
.singleResult();
Assert.notNull(processInstance, MyExceptionEnum.NULL_ACT_PROCESS_INSTANCE);
org.activiti.engine.task.Task task =
taskService.createTaskQuery().processInstanceId(req.getBody().getProcessInstanceId()).singleResult();
Assert.notNull(task, MyExceptionEnum.NULL_ACT_USER_TASK);
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
Assert.notNull(bpmnModel, MyExceptionEnum.NULL_ACT_BPMN_MODEL);
UserTask firstUserTask = ActivitiUtils.getFirstUserTasks(bpmnModel);
Assert.notNull(firstUserTask, MyExceptionEnum.NULL_ACT_USER_TASK);
List<UserTask> allUserTasks = ActivitiUtils.getAllUserTasks(bpmnModel);
Assert.notNull(allUserTasks, MyExceptionEnum.NULL_ACT_USER_TASK_DEFINITION);
GetInstanceRsp.GetInstanceRspBody rspBody = GetInstanceRsp.GetInstanceRspBody.builder()
.processInstanceId(processInstance.getId())
.processInstanceName(processInstance.getName())
.taskId(task.getId())
.taskName(task.getName())
.businessKey(task.getBusinessKey())
.historyTasks(new ArrayList<>())
.formProperties(firstUserTask.getFormProperties())
.build();
Collection<String> vals = new ArrayList<>();
vals.add(ActivitiUtils.getFormsKey());
rspBody.setVariables(runtimeService.getVariables(task.getExecutionId()));
GetInstanceRsp rsp = GetInstanceRsp.builder().body(rspBody).build();
List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
// 查询结果包括 local变量
.includeTaskLocalVariables()
.processInstanceId(processInstance.getId())
.orderByHistoricTaskInstanceStartTime()
.asc()
.list();
if (!CollectionUtils.isEmpty(historicTaskInstances)) {
for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
GetInstanceRsp.HistoricTask tempHistoricTask = GetInstanceRsp.HistoricTask.builder()
.taskId(historicTaskInstance.getId())
.name(historicTaskInstance.getName())
.createTime(historicTaskInstance.getCreateTime())
.build();
AssigneeVO tempAssigness = new AssigneeVO();
if (StringUtils.isEmpty(historicTaskInstance.getAssignee())) {
String assigneeKey = ActivitiUtils.getAssigneeKey(historicTaskInstance.getTaskDefinitionKey());
tempAssigness.setUsername((String) historicTaskInstance.getTaskLocalVariables().get(assigneeKey));
} else {
tempAssigness.setUsername(historicTaskInstance.getAssignee());
}
String name = userMapper.getNameByUserName(tempAssigness.getUsername());
if (!StringUtils.isEmpty(name)) {
tempAssigness.setName(name);
}
tempHistoricTask.setAssignee(tempAssigness);
// 获取comment
Optional<org.activiti.engine.task.Comment> commentOptional =
taskService.getTaskComments(historicTaskInstance.getId(), ActivitiUtils.getCommentKey())
.stream()
.findFirst();
if (commentOptional.isPresent()) {
tempHistoricTask.setComment(commentOptional.get().getFullMessage());
}
// 获取approve
Optional<org.activiti.engine.task.Comment> approveOptional =
taskService.getTaskComments(historicTaskInstance.getId(), ActivitiUtils.getApproveKey())
.stream()
.findFirst();
if (approveOptional.isPresent()) {
tempHistoricTask.setApprove(Integer.parseInt(approveOptional.get().getFullMessage()));
}
rspBody.getHistoryTasks().add(tempHistoricTask);
}
}
Deployment deployment =
repositoryService.createDeploymentQuery().deploymentId(processInstance.getDeploymentId()).singleResult();
Assert.notNull(deployment, MyExceptionEnum.NULL_ACT_USER_TASK);
// ProcessListener tempProcessListener =
// getProcessListenerByKey(deployment.getKey(), req.getBody().getBusinessKey());
// if (tempProcessListener != null) {
// String url =
// String.format(tempProcessListener.getCommActivity().getFormUrl(), req.getBody().getBusinessKey());
// rsp.getBody().setFormUrl(url);
// }
return rsp;
}
private ProcessListener getProcessListenerByKey(String deploymentKey, String businessKey) {
ProcessListener customProcessListener = ProcessListener.builder()
.deploymentKey(deploymentKey)
.businessKey(businessKey)
.commActivityMapper(commActivityMapper)
.callService(callService)
.build();
return customProcessListener;
}
}
ProcessesApiController.java
package ***.***.activiti.controller;
import com.bootdo.activiti.command.DeleteDeploymentCommand;
import com.bootdo.activiti.command.DeploymentByResourceCommand;
import com.bootdo.activiti.command.DeploymentByZipCommand;
import com.bootdo.activiti.command.SearchProcesseCommand;
import com.bootdo.activiti.enums.CommonResponseEnum;
import com.bootdo.activiti.interfaces.model.JsonResult;
import com.bootdo.activiti.interfaces.model.JsonResultPage;
import com.bootdo.activiti.model.CopyDeploymentToModel;
import com.bootdo.activiti.model.DeploymentResponseModel;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipInputStream;
@RestController
@RequestMapping(value = "/activiti/processes/api/",method = RequestMethod.POST)
@Api(value = "processes", tags = {"流程接口"})
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
public class ProcessesApiController {
private static final Logger LOGGER = LoggerFactory.getLogger(ProcessesApiController.class);
/**
* 流程定义和部署相关的存储服务
*/
@Resource
RepositoryService repositoryService;
@RequestMapping("/deploymentByResource")
@ApiOperation(value = "发布流程",notes = "项目内部资源文件部署")
public JsonResult deploymentByResource(@RequestBody DeploymentByResourceCommand command)
{
if(command==null || StringUtils.isEmpty(command.getName()) || StringUtils.isEmpty(command.getBpmpResourcePath()))
return JsonResult.error(CommonResponseEnum.Invalid_Parameter);
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
//创建Deployment对象
deploymentBuilder = deploymentBuilder.addClasspathResource(command.getBpmpResourcePath());
//添加png文件
if(!StringUtils.isEmpty(command.getPngResourcePath()))
deploymentBuilder = deploymentBuilder.addClasspathResource(command.getPngResourcePath());
//部署
Deployment deployment = deploymentBuilder.name(command.getName()).key(command.getKey()).deploy();
return JsonResult.success(deployment);
}
@RequestMapping("/categories")
@ApiOperation(value = "流程分类",notes = "获取所有流程分类")
public JsonResult categories()
{
List<String> categories = new ArrayList<String>(){
{
add("事假");
add("病假");
add("会议");
add("出差");
}
};
return JsonResult.success(categories);
}
@RequestMapping("/deploymentByZipFile")
@ApiOperation(value = "发布流程",notes = "外部 zip 文件部署")
public JsonResult deploymentByZipFile(@RequestBody DeploymentByZipCommand command) throws IOException {
if(command==null || StringUtils.isEmpty(command.getName()) || StringUtils.isEmpty(command.getZipFilePath()))
return JsonResult.error(CommonResponseEnum.Invalid_Parameter);
InputStream in=null;
ZipInputStream zipInputStream=null;
try {
in = new FileInputStream(new File(command.getZipFilePath()));
zipInputStream = new ZipInputStream(in);
Deployment deployment = repositoryService.createDeployment().name(command.getName())
// 指定zip格式的文件完成部署
.addZipInputStream(zipInputStream).deploy();// 完成部署
return JsonResult.success(deployment);
}
finally {
if(in!=null)
{
zipInputStream.close();
}
}
}
/**
* 删除已经部署的流程定义
* 影响的activiti表有哪些
* act_re_deployment 部署信息
* act_re_procdef 流程定义的一些信息
* act_ge_bytearray 流程定义的bpmn文件以及png文件
**/
@RequestMapping("/delete")
@ApiOperation(value = "删除已经部署的流程定义")
public JsonResult delete(@RequestBody DeleteDeploymentCommand command)
{
if(command==null || StringUtils.isEmpty(command.getDeploymentId()))
return JsonResult.error(CommonResponseEnum.Invalid_Parameter);
//删除流程定义 参数表述流程部署id 可以通过查询部署的信息得到流程部署id
repositoryService.deleteDeployment(command.getDeploymentId(),command.isCascade());
return JsonResult.success();
}
@RequestMapping("/list")
@ApiOperation(value = "查询已部署的流程",notes = "List<Deployment>")
public JsonResultPage list(@RequestBody SearchProcesseCommand command)
{
if(command==null)
return JsonResultPage.error(CommonResponseEnum.Invalid_Parameter);
DeploymentQuery query = repositoryService.createDeploymentQuery().orderByDeploymentName().desc();
if(!StringUtils.isEmpty(command.getName()))
query = query.deploymentName(command.getName());
if(!StringUtils.isEmpty(command.getKey()))
query = query.processDefinitionKey(command.getKey());
if(!StringUtils.isEmpty(command.getCategory()))
query = query.deploymentCategory(command.getCategory());
long total = query.count();
List<Deployment> deployments = query.orderByDeploymentName().asc()
.listPage((command.getPage()-1)*command.getLimit(),command.getLimit());
List<DeploymentResponseModel> processResponseModels = new ArrayList<>();
for (Deployment deployment : deployments) {
processResponseModels.add(
new DeploymentResponseModel(){
{
setDeploymentId(deployment.getId());
setName(deployment.getName());
setDeploymentTime(deployment.getDeploymentTime());
setCategory(deployment.getCategory());
setKey(deployment.getKey());
setTenantId(deployment.getTenantId());
}
}
);
}
return new JsonResultPage<>(processResponseModels,total,command.getLimit());
}
@RequestMapping("/copyToModel")
@ApiOperation(value = "复制已部署的流程模型")
public JsonResult copToModel(@RequestBody CopyDeploymentToModel command) throws IOException {
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(command.getDeploymentId()).singleResult();
if(deployment==null)
{
return JsonResult.error(CommonResponseEnum.Deployment_NotFind);
}
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(command.getDeploymentId()).singleResult();
if(processDefinition==null)
{
return JsonResult.error(CommonResponseEnum.ProcessDefinition_NotFind);
}
BpmnModel bpmnModel =repositoryService.getBpmnModel(processDefinition.getId());
if(processDefinition==null)
{
return JsonResult.error(CommonResponseEnum.BpmnModel_NotFind);
}
Model modelData = repositoryService.newModel();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, deployment.getName());
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
modelData.setMetaInfo(modelObjectNode.toString());
modelData.setName( deployment.getName());
modelData.setKey(deployment.getKey());
modelData.setCategory(deployment.getCategory());
modelData.setVersion(1);
//保存模型
repositoryService.saveModel(modelData);
//保存模型对应的流程图json
BpmnJsonConverter bpmnJsonConverter = new BpmnJsonConverter();
ObjectNode objectNode = bpmnJsonConverter.convertToJson(bpmnModel);
repositoryService.addModelEditorSource(modelData.getId(), objectNode.toString().getBytes("utf-8"));
return JsonResult.success(modelData.getId());
}
}
5.服务接口
SimpleUserTaskApiController.java
package ***.***.activiti.controller;
import com.bootdo.activiti.command.*;
import com.bootdo.activiti.enums.CommonResponseEnum;
import com.bootdo.activiti.enums.GlobalExceptionResponseEnum;
import com.bootdo.activiti.interfaces.model.JsonResult;
import com.bootdo.activiti.interfaces.model.JsonResultPage;
import com.bootdo.system.domain.DeptDO;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EventListener;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping(value = "/activiti/model/api/",method = RequestMethod.POST)
@Api(value = "model", tags = {"模型接口"})
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
public class ModelApiController {
/**
* 流程定义和部署相关的存储服务
*/
@Resource
RepositoryService repositoryService;
private static final Logger LOGGER = LoggerFactory.getLogger(ModelApiController.class);
/**
* 创建模型
*/
@RequestMapping("/create")
public JsonResult apiCreate(@RequestBody CreateModelCommand command) {
if(command==null || StringUtils.isEmpty(command.getName()) || StringUtils.isEmpty(command.getKey()))
return JsonResult.error(CommonResponseEnum.Invalid_Parameter);
// securityUtils.logInAs(command.getOperatedByUserName());
try {
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilSetNode);
Model modelData = repositoryService.newModel();
ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, command.getName());
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, command.getDescription());
modelData.setMetaInfo(modelObjectNode.toString());
modelData.setName( command.getName());
modelData.setKey(command.getKey());
modelData.setCategory(command.getCategory());
//保存模型
repositoryService.saveModel(modelData);
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
return JsonResult.success(modelData.getId());
} catch (Exception e) {
LOGGER.error("创建模型错误",e);
return JsonResult.error(GlobalExceptionResponseEnum.RuntimeException);
}
}
/**
* 查询模型列表
* @param command
* @return
*/
@RequestMapping("/list")
public JsonResultPage<Model> apiList(@RequestBody SearchModelCommand command)
{
if(command==null)
return JsonResultPage.error(CommonResponseEnum.Invalid_Parameter);
ModelQuery modelQuery =repositoryService.createModelQuery().orderByModelCategory().desc();
if(!StringUtils.isEmpty(command.getName()))
modelQuery = modelQuery.modelName(command.getName());
if(!StringUtils.isEmpty(command.getKey()))
modelQuery = modelQuery.modelKey(command.getKey());
if(!StringUtils.isEmpty(command.getCategory()))
modelQuery = modelQuery.modelCategory(command.getCategory());
long total = modelQuery.count();
List<Model> modelList = modelQuery.listPage((command.getPage()-1)*command.getLimit(),command.getLimit());
return new JsonResultPage(modelList,total,command.getLimit());
}
/**
* 删除模型
* @param command
* @return
*/
@RequestMapping("/delete")
public JsonResult apiDelete(@RequestBody DeleteModelCommand command)
{
if(command==null || StringUtils.isEmpty(command.getModelId()))
return JsonResult.error(CommonResponseEnum.Invalid_Parameter);
// securityUtils.logInAs(command.getOperatedByUserName());
repositoryService.deleteModel(command.getModelId());
return JsonResult.success();
}
/**
* 发布模型
* @param command
* @return
*/
@RequestMapping("/deployment")
public JsonResult apiDeployment(@RequestBody DeploymentModelCommand command) throws Exception
{
if(command==null || StringUtils.isEmpty(command.getModelId()))
return JsonResult.error(CommonResponseEnum.Invalid_Parameter);
// securityUtils.logInAs(command.getOperatedByUserName());
//获取模型
Model modelData = repositoryService.getModel(command.getModelId());
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (bytes == null) {
LOGGER.info("模型数据为空,请先设计流程并成功保存,再进行发布。");
return JsonResult.error(CommonResponseEnum.Model_NotFind);
}
JsonNode modelNode = new ObjectMapper().readTree(bytes);
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);
List<Process> processes = bpmnModel.getProcesses();
if (CollectionUtils.isEmpty(processes)) {
LOGGER.info("数据模型不符要求,请至少设计一条主线流程。");
return JsonResult.error(CommonResponseEnum.Model_LeastOneMainProcess);
}
for (Process process: processes) {
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
if(!command.isIgnoreDuplicates())
{
int rows = repositoryService.createProcessDefinitionQuery().processDefinitionKey(modelData.getKey()).list().size();
if(rows>0)
{
return JsonResult.error(CommonResponseEnum.Duplicate_key);
}
}
//发布流程
String processName = modelData.getName() + ".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment()
.name(modelData.getName())
.key(modelData.getKey())
.category(StringUtils.isEmpty(modelData.getCategory())?"其它":modelData.getCategory())
.addString(processName, new String(bpmnBytes, "UTF-8"))
.deploy();
//发布完毕,删除模型
if(command.isDeleteModel())
repositoryService.deleteModel(command.getModelId());
return JsonResult.success(deployment);
}
}
6.自定义全局侦听器
CustomGlobalActivitiEventListener.java
package ***.***.activiti7.listeners;
import java.util.Date;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.delegate.event.ActivitiEntityEvent;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiProcessStartedEvent;
import org.activiti.engine.delegate.event.impl.ActivitiEntityEventImpl;
import org.activiti.engine.delegate.event.impl.ActivitiEntityWithVariablesEventImpl;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import ***.***.activiti7.mapper.CommActivityMapper;
import ***.***.activiti7.util.ActivitiUtils;
import ***.***.intf.service.CallService;
import net.platform.center.util.ApplicationContextHolder;
/**
* @ClassName WsjActivitiEventListener
* @Description: 全局
* @Author wsj
* @Date 2020/8/19
**/
@Component
public class CustomGlobalActivitiEventListener implements ActivitiEventListener {
/**
* 流程定义和部署相关的存储服务
* 不自动注入,是应为油循环依赖问题
*/
@Override
public void onEvent(ActivitiEvent activitiEvent) {
ProcessListener processListener;
switch (activitiEvent.getType()) {
// 流程开始
case PROCESS_STARTED:
if (activitiEvent instanceof ActivitiProcessStartedEvent) {
ExecutionEntity executionEntity =
(ExecutionEntity) ((ActivitiProcessStartedEvent) activitiEvent).getEntity();
processListener = getProcessListener(activitiEvent);
if (processListener == null) {
break;
}
if (executionEntity.getTasks().size() != 1) {
break;
}
processListener.instanceId = activitiEvent.getProcessInstanceId();
processListener.businessKey = executionEntity.getTasks().get(0).getBusinessKey();
processListener.taskName = "发起审批";
processListener.state = 1;
TaskEntity taskEntity = executionEntity.getTasks().get(0);
if (StringUtils.isEmpty(taskEntity.getAssignee())) {
String key = ActivitiUtils.getAssigneeKey(taskEntity.getTaskDefinitionKey());
processListener.by = processListener.nextBy = (String) taskEntity.getVariable(key);
taskEntity.setAssignee(processListener.by);
} else {
processListener.by = processListener.nextBy = executionEntity.getTasks().get(0).getAssignee();
}
processListener.at = new Date();
processListener.processStarted(executionEntity);
}
break;
case PROCESS_COMPLETED:
processListener = getProcessListener(activitiEvent);
if (processListener == null) {
break;
}
if (activitiEvent instanceof ActivitiEntityEvent) {
ActivitiEntityEvent activitiEntityEvent = (ActivitiEntityEvent) activitiEvent;
ExecutionEntity executionEntity = (ExecutionEntity) activitiEntityEvent.getEntity();
processListener.instanceId = activitiEvent.getProcessInstanceId();
processListener.businessKey = executionEntity.getBusinessKey();
processListener.at = executionEntity.getStartTime();
// .get(executionEntity.getIdentityLinks().size() - 1)
// .getUserId();
int approve = (int) executionEntity.getVariable(ActivitiUtils.getApproveKey());
if (approve == ActivitiUtils.APPROVE_PASS) {
// #TODO 需要判断是通过还是不通过,不过目前是单线程,到达终止节点,就表示通过
processListener.taskName = "审批通过";
processListener.state = 2;
} else if (approve == ActivitiUtils.APPROVE_UN_PASS) {
// #TODO 需要判断是通过还是不通过,不过目前是单线程,到达终止节点,就表示通过
processListener.taskName = "审批不通过";
processListener.state = 3;
} else if (approve == ActivitiUtils.APPROVE_END) {
// #TODO 需要判断是通过还是不通过,不过目前是单线程,到达终止节点,就表示通过
processListener.taskName = "审批终止";
processListener.state = 4;
processListener.nextBy = null;
} else {
processListener.taskName = "未知";
processListener.state = 5;
}
// 一定要 getCommActivity(),不然没值
processListener.getCommActivity();
processListener.processCompleted(executionEntity);
}
break;
case TASK_CREATED:
if (activitiEvent instanceof ActivitiEntityEventImpl) {
processListener = getProcessListener(activitiEvent);
if (processListener == null) {
break;
}
ActivitiEntityEventImpl entityEvent = (ActivitiEntityEventImpl) activitiEvent;
TaskEntityImpl taskEntity = (TaskEntityImpl) entityEvent.getEntity();
processListener.instanceId = activitiEvent.getProcessInstanceId();
processListener.businessKey = taskEntity.getBusinessKey();
if (StringUtils.isEmpty(taskEntity.getAssignee())) {
String key = ActivitiUtils.getAssigneeKey(taskEntity.getTaskDefinitionKey());
processListener.nextBy = (String) taskEntity.getVariable(key);
taskEntity.setAssignee(processListener.nextBy);
} else {
processListener.nextBy = taskEntity.getAssignee();
}
processListener.taskCreated(taskEntity);
}
break;
case TASK_COMPLETED:
if (activitiEvent instanceof ActivitiEntityWithVariablesEventImpl) {
processListener = getProcessListener(activitiEvent);
if (processListener == null) {
break;
}
ActivitiEntityWithVariablesEventImpl entityEvent =
(ActivitiEntityWithVariablesEventImpl) activitiEvent;
TaskEntity taskEntity = (TaskEntity) entityEvent.getEntity();
processListener.instanceId = activitiEvent.getProcessInstanceId();
processListener.businessKey = taskEntity.getBusinessKey();
processListener.at = taskEntity.getCreateTime();
if (StringUtils.isEmpty(taskEntity.getAssignee())) {
processListener.by = ActivitiUtils.getAssigneeKey(taskEntity.getTaskDefinitionKey());
} else {
processListener.by = taskEntity.getAssignee();
}
processListener.taskName = taskEntity.getName();
int approve = (int) taskEntity.getVariable(ActivitiUtils.getApproveKey());
switch (approve) {
case ActivitiUtils.APPROVE_BACK:
processListener.state = 5;
break;
case ActivitiUtils.APPROVE_END:
processListener.state = 4;
processListener.nextBy = null;
processListener.taskName = "审批终止";
break;
default:
processListener.state = 1;
break;
}
processListener.taskCompleted(taskEntity);
}
break;
default:
break;
}
}
private RepositoryService getRepositoryService() {
return ApplicationContextHolder.getBean(RepositoryService.class);
}
private CommActivityMapper getCommActivityMapper() {
return ApplicationContextHolder.getBean(CommActivityMapper.class);
}
private CallService getCallService() {
return ApplicationContextHolder.getBean(CallService.class);
}
private ProcessListener getProcessListener(ActivitiEvent activitiEvent) {
RepositoryService repositoryService = getRepositoryService();
if (repositoryService == null) {
return null;
}
// 获取流程定义
ProcessDefinition processDefinition =
repositoryService.getProcessDefinition(activitiEvent.getProcessDefinitionId());
if (processDefinition == null) {
return null;
}
Deployment deployment =
repositoryService.createDeploymentQuery().deploymentId(processDefinition.getDeploymentId()).singleResult();
if (deployment == null) {
return null;
}
ProcessListener processListener = new ProcessListener();
processListener.setCommActivityMapper(getCommActivityMapper());
processListener.setCallService(getCallService());
processListener.setDeploymentKey(deployment.getKey());
return processListener;
}
/**
* 这个是必须要的,监听异常处理策略
*
* @return
*/
@Override
public boolean isFailOnException() {
return false;
}
}
业务列表中,需要显示目前是在哪个审批环节,各位根据自己实际业务看看是否需要
CustomerActivitiConfig.java
package ***.***.activiti7;
import java.util.ArrayList;
import java.util.List;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ***.***.activiti7.listeners.CustomGlobalActivitiEventListener;
@Component
public class CustomerActivitiConfig implements ProcessEngineConfigurationConfigurer {
@Autowired
private CustomGlobalActivitiEventListener customGlobalActivitiEventListener;
@Override
public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
List<ActivitiEventListener> eventListeners = new ArrayList<>();
eventListeners.add(customGlobalActivitiEventListener);
springProcessEngineConfiguration.setEventListeners(eventListeners);
}
}
IProcessListener.java
package ***.***.activiti7.listeners;
import java.text.ParseException;
import java.util.Date;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import ***.***.activiti7.bean.CommActivityPO;
import ***.***.intf.service.CallService;
public interface IProcessListener {
// #region 属性、变量
// String getKeyFileName();
String getInstanceId();
String getBusinessKey();
Integer getState();
String getTaskName();
String getBy();
String getNextBy();
Date getAt();
CommActivityPO getCommActivity();
String getDeploymentKey();
// #endregion
// #region 方法
CallService getCallService();
/**
* 流程开始
*/
void processStarted(ExecutionEntity executionEntity);
/**
* 流程结束
*/
void processCompleted(ExecutionEntity executionEntity) throws ParseException;
/**
* 任务完成
*/
void taskCompleted(TaskEntity taskEntity);
/**
* 任务创建
*/
void taskCreated(TaskEntity taskEntity);
/**
* 检查是否允许开启流程
*
* @return
*/
boolean checkCanStart();
// #endregion
}
ProcessListener.java
package ***.***.activiti7.listeners; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.persistence.entity.VariableInstance; import org.springframework.context.annotation.Scope; import org.springframework.http.ResponseEntity; import ***.***.activiti7.bean.CallBackReq; import ***.***.activiti7.bean.CallBackRsp; import ***.***.activiti7.bean.CommActivityPO; import ***.***.activiti7.mapper.CommActivityMapper; import ***.***.intf.service.CallService; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.platform.center.util.JsonUtil; @Slf4j @AllArgsConstructor @NoArgsConstructor @Data @Builder @Scope("prototype") public class ProcessListener implements IProcessListener { // /** // * 主键字段名 // */ // protected String keyFileName; /** * 流程实例ID */ protected String instanceId; /** * 业务数据主键 */ protected String businessKey; /** * 审批状态 * 1:发起审批 * 2:审批通过 * 3:审批不通过 * 4:审批终止 * 5:退回 * 6:未知 */ protected Integer state; /** * 当前环节 */ protected String taskName; /** * 本环节审批人 */ protected String by; /** * 下一个环节审批人 */ protected String nextBy; /** * 审批时间 */ protected Date at; private String deploymentKey; private CommActivityPO commActivity; private CommActivityMapper commActivityMapper; private CallService callService; @Override public CommActivityPO getCommActivity() { if (commActivity == null) { commActivity = commActivityMapper.get(deploymentKey); } return commActivity; } @Override public void processStarted(ExecutionEntity executionEntity) { commActivityMapper.processStarted(this); if (getCommActivity() != null && getCommActivity().isProcessStartedCallBack()) { CallBackRsp callBackRsp = callBack("processStartedCallBackUrl", executionEntity.getProcessVariables()); // #TODO 判断 CallBackRsp,输出日志 log.info("processStarted processStartedCallBackUrl: {}", callBackRsp.toString()); } } @Override public void processCompleted(ExecutionEntity executionEntity) { commActivityMapper.processCompleted(this); if (getCommActivity() != null && getCommActivity().isProcessCompletedCallBack()) { Map<String, VariableInstance> variableInstances = executionEntity.getVariableInstances(); Map<String, Object> data = new HashMap<>(); // 1. entrySet遍历,在键和值都需要时使用(最常用) for (Map.Entry<String, VariableInstance> entry : variableInstances.entrySet()) { data.put(entry.getKey(), entry.getValue().getValue()); } CallBackRsp callBackRsp = callBack("processCompletedCallBackUrl", data); log.info("processCompleted processCompletedCallBackUrl: {}", JsonUtil.toJsonString(callBackRsp)); } } @Override public void taskCompleted(TaskEntity taskEntity) { commActivityMapper.taskCompleted(this); if (getCommActivity() != null && getCommActivity().isTaskCompletedCallBack()) { CallBackRsp callBackRsp = callBack("taskCompletedCallBackUrl", taskEntity.getVariables()); // #TODO 判断 CallBackRsp,输出日志 log.info("taskCompleted taskCompletedCallBackUrl: {}", JsonUtil.toJsonString(callBackRsp)); } } @Override public void taskCreated(TaskEntity taskEntity) { commActivityMapper.taskCreated(this); } @Override public boolean checkCanStart() { // 检查后是否已经发起了审批 int result = commActivityMapper.getProcessStarted(this); if (result == 1) { return false; } CallBackReq callBackReq = CallBackReq.builder() .body(CallBackReq.CallBackReqBody.builder() .deploymentKey(this.deploymentKey) .businessKey(this.businessKey) .build()) .build(); if (getCommActivity() != null && getCommActivity().isCheckCanStartCallBack()) { CallBackRsp callBackRsp = callBack("checkCanStartCallBackUrl", callBackReq); return "1".equals(callBackRsp.getCode()); } else { return true; } } private CallBackRsp callBack(String serviceName, Object data) { CallBackReq req = CallBackReq.builder() .body(CallBackReq.CallBackReqBody.builder() .businessKey(businessKey) .deploymentKey(deploymentKey) .data(data) .build()) .build(); ResponseEntity<CallBackRsp> responseEntity = callService.callService(serviceName, req, CallBackRsp.class); log.info("callService req: {}", req.toString()); log.info("callService rsp: {}", JsonUtil.toJsonString(responseEntity)); return responseEntity.getBody(); } @Override public String toString() { return "ProcessListener(instanceId=" + instanceId + ", businessKey=" + businessKey + ", state=" + state + ", taskName=" + taskName + ", by=" + by + ", nextBy=" + nextBy + ", at=" + at + ", deploymentKey=" + deploymentKey + ")"; } }
工作流配置表

浙公网安备 33010602011771号