经过了长时间的学习和探索,对activiti的工作流有了初步的认识,也积累下了些许经验分享给大家
不足之处以及建议欢迎指正~
开发环境:activiti5.22.0 springboot1.5.4
流程设计使用的是集成的activiti流程设计器
部署流程
/**
* 发布模型为流程实例
*/
@ApiOperation(value = "发布模型为流程定义")
@PostMapping("{id}/deployment")
public R deploy(@PathVariable("id") String id) throws Exception {
//获取模型
RepositoryService repositoryService = processEngine.getRepositoryService();
Model modelData = repositoryService.getModel(id);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (bytes == null) {
return R.error("模型数据为空,请先设计流程并成功保存,再进行发布。");
}
JsonNode modelNode = new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
if (model.getProcesses().size() == 0) {
return R.error("数据模型不符要求,请至少设计一条主线流程。");
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
//发布流程
String processName = modelData.getName() + ".bpmn20.xml";
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.name(modelData.getName())
.addString(processName, new String(bpmnBytes, "UTF-8"));
Deployment deployment = deploymentBuilder.deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);
return R.ok();
}
获取工作流流程模型列表(带分页):
/**
* 获取流程model列表(分页)
*/
@RequestMapping(value = "/list", method = RequestMethod.POST)
public TableResultResponse<Model> list(@RequestParam Map<String, Object> params) {
int page = Integer.parseInt((String) params.get("page"));
int limit = Integer.parseInt((String) params.get("limit"));
Page<Object> result = PageHelper.startPage(page, limit);
List<Model> list = repositoryService.createModelQuery().orderByCreateTime().desc().list();
return new TableResultResponse<Model>(result.getTotal(), list);
}
删除流程模型:
/**
* 删除模型
*/
@DeleteMapping("{id}")
@ApiOperation(value = "删除模型")
public Object deleteModel(@PathVariable("id") String id) {
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.deleteModel(id);//删除模型
repositoryService.deleteDeployment(id, true);//如果存在运行中的流程,级联删除设置为true
return R.ok();
}
工作流运行
public R startProcess() {
String processDefinitionKey = "获取流程设计的key";
ProcessInstance instance = null;
//判断是否存在流程部署
List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionKey)//根据流程定义的key查询
.list();
if(list != null && list.size() > 0) {
//启动流程实例(指定下级经办人)
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("user", "获取下级经办人");
instance = processEngine.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey, variables);
} else {
//流程未部署,或其他情况
return R.ok("流程未部署,请检查流程定义").put("code", 500);
}
if(instance != null) {
//流程启动成功
System.out.println("流程实例id=" + instance.getProcessInstanceId());
System.out.println("流程实例name=" + instance.getName());
return R.ok().put("data", "流程启动成功");
} else {
return R.ok("未获取到流程实例,请检查是否发布!").put("code", 500);
}
}
流程启动的时候,可以动态指定下级经办人,或者不指定下级经办人而在流程设计中设置好,直接启动流程即可:
processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
流程删除
/**
* 删除流程实例
* @param processInstanceId
*/
@RequestMapping(value = "/deleteWf/{processInstanceId}", method = RequestMethod.DELETE)
public void delete(@PathVariable("processInstanceId") String processInstanceId){
runtimeService.deleteProcessInstance(processInstanceId, "删除流程实例原因");
}
根据用户获取待办任务列表,或任务个数(接口中的userID为实际业务中assignee设置的为人员id)
/**
* 根据用户ID获取用户待办任务个数
*/
public int taskCountByUserID(String userID) {
int count = count = count + taskService.createTaskQuery().taskAssignee(userID).list().size();
return count;
}
/**
* 根据用户ID获取用户待办任务列表
*/
public List<Task> taskList(String userID) {
//查询个人任务列表
List<Task> taskList = taskService.createTaskQuery().taskAssignee(userID).list();
return taskList;
}
审批
@RequestMapping(value = "/complete/{taskID}", method = RequestMethod.GET)
@ApiOperation("审批通过,添加信息")
public R copmlete(@PathVariable("taskID") String taskID) {
//查询是否有正在审批任务
Task task = taskService.createTaskQuery().taskId(taskID).singleResult();
if(task != null) {
//完成审批任务
taskService.complete(taskID);
//如果需要传递参数的话 task.getProcessInstanceId()获取processInstanceId
//runtimeService.setVariable(processInstanceId, "变量名", 参数);全局变量
//taskService.setVariableLocal(taskID, "变量名", 参数);局部变量,该task下
//添加批注的方法
//taskService.addComment(taskID, processInstanceId, "批注信息");
}
return R.ok("审批成功");
}
驳回的流程设计需要节点的流转,设置好条件进行判断流转方向
会签(多实例)的设计,在该业务中设计的是多实例并行任务
将多实例任务设置为Parallel并行,设置参数变量,可以通过监听器将会签人员集合传递进来,也可以在上级节点指定参数传递
public class CompleteListener implements TaskListener {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void notify(DelegateTask delegateTask) {
List<String> assigneeList = new ArrayList<String>();
assigneeList.add("部门一");
assigneeList.add("部门二");
delegateTask.setVariable("assigneeList", assigneeList);
}
}
添加监听器设置会签人员集合
历史记录表的应用:
act_hi_actinst:历史节点信息表,审批节点的历史记录,可以获取历史活动节点的信息
act_hi_comment:历史审批记录表,可以获取审批批注信息
act_hi_procinst:历史流程实例表,可以获取历史流程实例的运行记录如是否结束,开始时间,结束时间等
act_hi_taskinst:历史任务信息表,可以获取历史任务的审批记录信息,审批人,审批时间
act_hi_varinst:历史流程变量表,可以获取历史流程实例下的流程变量信息,如存放的审批信息等
问题汇总
1. 获取审批批注信息问题
开发过程中,添加审批批注成功,但是部署生成环境是CentOS,发现存在获取乱码的情况
//获取批注信息
List<Comment> comments = processEngine.getTaskService()
.getTaskComments(historicActivityInstance.getTaskId());
Comment对象提供的api获取的是FULL_MSG_字段的blob类型文件信息,存在乱码现象,其中一种解决方式:
定义新的MyCommentEntity接收对象获取message信息
List<MyCommentEntity> myCommentEntities = new ArrayList<MyCommentEntity>();
if(comments != null && comments.size() > 0) {
//创建我们自己的list集合
//为每一个查询到接口实现类复制属性到我们自己的类中,解析为前端JSON数据
for(Comment comment :comments){
//创建我们自己的类
MyCommentEntity myCommentEntity = new MyCommentEntity();
//属性复制,源属性为commentEntity, 目标属性为myCommentEntity
BeanUtils.copyProperties(comment, myCommentEntity);
//添加我们自己的类
myCommentEntities.add(myCommentEntity);
}
//get批注信息即可
//list.get(0).getMessage();
}
MyCommentEntity实体类:
@Getter
@Setter
public class MyCommentEntity {
private String id;
private String userId;//用户名,对应的是act_hi_comment表的USER_ID_字段
private Date date;
private String taskId;//任务id
private String processInstanceId;//流程定义id
private String message;//审批信息
private String fullMessage;
}