这里主要记录一下activiti常用的一些操作
1.部署一个Activiti流程
部署流程有几种方式,常见的就是通过bpmn和png文件部署,还有通过zip压缩文件部署
public void creatActivitiTask() {
// 获取部署对象
Deployment deployment = repositoryService
.createDeployment() // 创建部署
.name("T3") // 流程名称
.addClasspathResource("bpmn/T3.bpmn") // 加载资源文件
.addClasspathResource("bpmn/T1.png") // 加载资源文件
.deploy(); // 部署
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署Name:" + deployment.getName());
}
public void deployProcessSubmit(MultipartFile resource_bpmn, MultipartFile resource_png) throws Exception {
//第一步:上传文件
//springmvc通过文件上传的参数解析器将页面提交的file赋值为形参
//resource_bpmn和resource_png存储了上传的文件
//第二步:调用activiti的service执行流程定义部署
//部署bpmn文件和png文件
//bpmn上传文件名
String resourceName_bpmn = resource_bpmn.getOriginalFilename();
InputStream inputStream_bpmn = resource_bpmn.getInputStream();
//png上传文件名
String resourceName_png = resource_png.getOriginalFilename();
InputStream inputStream_png = resource_png.getInputStream();
//部署对象
Deployment deployment = processEngine.getRepositoryService().createDeployment()
.addInputStream(resourceName_bpmn, inputStream_bpmn)//部署bpmn
.addInputStream(resourceName_png, inputStream_png)//部署png
.deploy();
//部署id
System.out.println("部署id:"+deployment.getId());
System.out.println("部署时间:" + deployment.getDeploymentTime());
}
public Result deployProcessZip(MultipartFile file, String processName) throws IOException {
Result result = new Result();
InputStream inputStream = file.getInputStream();
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
repositoryService
.createDeployment()
.name(processName)
.addZipInputStream(zipInputStream)
.deploy();
return result;
}
2.启动流程实例
public void testStartProcessInstance() {
Map<String, Object> variables = new HashMap<>();
variables.put("user", "耶耶耶");
// 启动并获取流程实例
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("T3", "T.3.1", variables); //还可以通过ID等方式启动,具体可查看RuntimeService相关接口
System.out.println("流程实例ID:" + processInstance.getId());
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
}
3.获取所有流程定义
如果只查询每种流程的最新版本,可以加上 .latestVersion()就行了,当然也可以通过如下代码形式也行
public Result getAllProcessList() {
Result result = new Result();
List<ProcessDefinition> list = repositoryService
.createProcessDefinitionQuery()
// .latestVersion() // 只查询最新版本
/*指定查询条件,where条件*/
//.deploymentId(deploymentId)//使用部署对象ID查询
//.processDefinitionId(processDefinitionId)//使用流程定义ID查询
//.processDefinitionKey(processDefinitionKey)//使用流程定义的KEY查询
//.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
.orderByProcessDefinitionVersion().asc()//使用流程定义的版本升序排列
.list()
//.count();//返回结果集数量
//.listPage(firstResult, maxResults)//分页查询
;
/*
* Map<String,ProcessDefinition>
* map集合的key:流程定义的key
* map集合的value:流程定义的对象
* 特点:当map集合key值相同的情况下,后一次的值将替换前一次的值
*/
Map<String, ProcessDefinition> map = new LinkedHashMap<>();
if (list != null && list.size() > 0) {
for (ProcessDefinition pd : list) {
map.put(pd.getKey(), pd);
}
}
List<ProcessDefinition> pdList = new ArrayList<>(map.values());
if (pdList.size() > 0) {
for (ProcessDefinition pd : pdList) {
System.out.println("流程定义ID:" + pd.getId());//流程定义的key+版本+随机生成数
System.out.println("流程定义的名称:" + pd.getName());//对应helloworld.bpmn文件中的name属性值
System.out.println("流程定义的key:" + pd.getKey());//对应helloworld.bpmn文件中的id属性值
System.out.println("流程定义的版本:" + pd.getVersion());//当流程定义的key值相同的相同下,版本升级,默认1
System.out.println("资源名称bpmn文件:" + pd.getResourceName());
System.out.println("资源名称png文件:" + pd.getDiagramResourceName());
System.out.println("部署对象ID:" + pd.getDeploymentId());
System.out.println("#########################################################");
}
}
return result;
}
4.获取指定流程协议列表(历史版本记录)
public Result getProcessList(String processDefinitionKey) {
Result result = new Result();
List<ProcessDefinition> list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
/*指定查询条件,where条件*/
//.deploymentId(deploymentId)//使用部署对象ID查询
//.processDefinitionId(processDefinitionId)//使用流程定义ID查询
.processDefinitionKey(processDefinitionKey)//使用流程定义的KEY查询
//.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
.orderByProcessDefinitionVersion().desc()//使用流程定义的版本升序排列
.list()
//.count();//返回结果集数量
//.listPage(firstResult, maxResults)//分页查询
;
result.addData("list", list);
return result;
}
5.执行任务
public Result completeProcess(String taskId) {
Result result = new Result();
Map<String, Object> variables = new HashMap<>();
variables.put("user", "q"); //此处就是上一章当中所说的给TaskListener传参
taskService.complete(taskId, variables); // 根据任务ID执行任务 执行任务后,会自动根据条件跳转到下一任务
// variables.put("money", 999); //这是对应流程当中连线的传参,因为没有默认连线,所以当不传此参数的时候,执行任务会报错
// taskService.complete(taskId, variables);
// taskService.complete(taskId); //这种则是没有其他条件,当该节点用户获取自己任务后执行即可
return result;
}
6.获取指定用户的任务列表
public Result getUserTaskList(String userId) {
Result result = new Result();
int startPage = 1;
int pageSize = 10;
//根据办理人来查询
List<Task> list = taskService.createTaskQuery()// 创建任务查询
.taskAssignee(userId)//按照当前输人查询
.list();
// .orderByTaskCreateTime().desc()// 按任务创建时间排序,倒序排序
// .listPage(startPage, pageSize);// 分页查询出任务列表
for(Task task : list){
System.out.println("任务ID:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务创建时间:"+task.getCreateTime());
System.out.println("任务委派人:"+task.getAssignee());
System.out.println("流程实例ID:"+task.getProcessInstanceId());
}
System.out.println("==============================================");
//此处list是只有当办理人为空,并且设置了签收人的时候可查询到任务节点,例如按照前一章说到的TaskListener里面添加多个签收人或者用户组,此时所有人都可以获取该节点任务
//但当签收人其中任何一人签收后,即该用户成为了办理人,那么其他人则无法在获取,通过打印sql语句可知道该list的查询语句是设置的办理人字段为空才查询签收人
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(userId).list();
for(Task task : tasks){
System.out.println("任务ID:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务创建时间:"+task.getCreateTime());
System.out.println("任务委派人:"+task.getAssignee());
System.out.println("流程实例ID:"+task.getProcessInstanceId());
}
return result;
}
7.查询指定用户历史任务
public Result findHistoryTask(String userId) {
Result result = new Result();
List<HistoricTaskInstance> list = historyService//与历史数据(历史表)相关的Service
.createHistoricTaskInstanceQuery()//创建历史任务实例查询
// .taskCandidateUser(userId)
.taskAssignee(userId)//指定历史任务的办理人
.list();
if (list != null && list.size() > 0) {
for (HistoricTaskInstance hti : list) {
System.out.println(hti.getId() + " " + hti.getName() + " " + hti.getProcessInstanceId() + " " + hti.getStartTime() + " " + hti.getEndTime() + " " + hti.getDurationInMillis());
System.out.println("################################");
}
}
return result;
}
8.查询流程实例历史纪录
public Result findHistoryProcessInstance() {
Result result = new Result();
String processInstanceId = "167501";
HistoricProcessInstance hpi = historyService//与历史数据(历史表)相关的Service
.createHistoricProcessInstanceQuery()//创建历史流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
System.out.println(hpi.getId() + " " + hpi.getProcessDefinitionId() + " " + hpi.getStartTime() + " " + hpi.getEndTime() + " " + hpi.getDurationInMillis());
return result;
}
9.根据业务键获取流程实例和任务
public Result getTaskByBusinessKey() {
Result result = new Result();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey("T3.1").singleResult();
List<Task> task = taskService.createTaskQuery().processInstanceBusinessKey("T3.1").list();
return result;
}
10.强制跳转
public void jump(String taskId) {
//当前任务
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
//获取流程定义
Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess();
//获取目标节点定义
FlowNode targetNode = (FlowNode) process.getFlowElement("申请报销"); //跳转到哪个节点
//删除当前运行任务
String executionEntityId = managementService.executeCommand(new DeleteTaskCmd(currentTask.getId()));
//流程执行到来源节点
managementService.executeCommand(new SetFLowNodeAndGoCmd(targetNode, executionEntityId));
}
/**
* discription: 删除当前运行时任务命令,并返回当前任务的执行对象id
* 这里继承了NeedsActiveTaskCmd,主要时很多跳转业务场景下,要求不能时挂起任务。可以直接继承Command即可
*
* @author luobin@jouav.com
* @date 2019/1/8 0008 13:17
*/
public class DeleteTaskCmd extends NeedsActiveTaskCmd<String> {
public DeleteTaskCmd(String taskId){
super(taskId);
}
public String execute(CommandContext commandContext, TaskEntity currentTask){
//获取所需服务
TaskEntityManagerImpl taskEntityManager = (TaskEntityManagerImpl)commandContext.getTaskEntityManager();
//获取当前任务的来源任务及来源节点信息
ExecutionEntity executionEntity = currentTask.getExecution();
//删除当前任务,来源任务
taskEntityManager.deleteTask(currentTask, "jumpReason", false, false);
return executionEntity.getId();
}
public String getSuspendedTaskException() {
return "挂起的任务不能跳转";
}
}
/**
* discription: 根据提供节点和执行对象id,进行跳转命令
*
* @author luobin@jouav.com
* @date 2019/1/8 0008 13:19
*/
public class SetFLowNodeAndGoCmd implements Command<Void> {
private FlowNode flowElement;
private String executionId;
public SetFLowNodeAndGoCmd(FlowNode flowElement,String executionId){
this.flowElement = flowElement;
this.executionId = executionId;
}
public Void execute(CommandContext commandContext){
//获取目标节点的来源连线
List<SequenceFlow> flows = flowElement.getIncomingFlows();
if(flows==null || flows.size()<1){
throw new ActivitiException("回退错误,目标节点没有来源连线");
}
//随便选一条连线来执行,时当前执行计划为,从连线流转到目标节点,实现跳转
ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findById(executionId);
executionEntity.setCurrentFlowElement(flows.get(0));
commandContext.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true);
return null;
}
}
11.单个流程实例挂起
public Result HangUp() {
Result result = new Result();
String processInstanceId = "";
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
boolean suspend = processInstance.isSuspended();
if (suspend) {
//如果暂停则激活
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "激活");
} else {
//如果激活则挂起
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "挂起");
}
String processDefinitionId = "";
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
//是否暂停
boolean suspend1 = processDefinition.isSuspended();
if (suspend1) {
//如果暂停则激活,这里将流程定义下的所有流程实例全部激活
repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
System.out.println("流程定义:" + processDefinitionId + "激活");
} else {
//如果激活则挂起,这里将流程定义下的所有流程实例全部挂起
repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
System.out.println("流程定义:" + processDefinitionId + "挂起");
}
return result;
}
12.通过taskId获取BusinessKey
public Result getBusinessKeyByTaskId(String taskId) {
Result result = new Result();
//1 获取任务对象
Task task = processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
System.out.println("=============================================");
//2 通过任务对象获取流程实例
ProcessInstance pi = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
System.out.println("=============================================");
//3 通过流程实例获取“业务键”
String businessKey = pi.getBusinessKey();
//4 拆分业务键,拆分成“业务对象名称”和“业务对象ID”的数组
// a=b LeaveBill.1
String objId = null;
if (StringUtils.isNotBlank(businessKey)) {
objId = businessKey.split("\\.")[1];
}
System.out.println(objId);
return result;
}
13.历史活动查询
public Result historyActInstanceList(String processInstanceId) {
Result result = new Result();
List<HistoricActivityInstance> list = historyService // 历史任务Service
.createHistoricActivityInstanceQuery() // 创建历史活动实例查询
.processInstanceId(processInstanceId) // 指定流程实例id
// .finished() // 查询已经完成的任务
.list();
for (HistoricActivityInstance hai : list) {
System.out.println("任务ID:" + hai.getId());
System.out.println("流程实例ID:" + hai.getProcessInstanceId());
System.out.println("活动名称:" + hai.getActivityName());
System.out.println("办理人:" + hai.getAssignee());
System.out.println("开始时间:" + hai.getStartTime());
System.out.println("结束时间:" + hai.getEndTime());
System.out.println("===========================");
}
return result;
}
14.历史任务查询
public Result historyTaskList(String taskAssignee) {
Result result = new Result();
List<HistoricTaskInstance> list = processEngine.getHistoryService() // 历史任务Service
.createHistoricTaskInstanceQuery() // 创建历史任务实例查询
.taskAssignee(taskAssignee) // 指定办理人
// .finished() // 查询已经完成的任务
.list();
for (HistoricTaskInstance hti : list) {
System.out.println("任务ID:" + hti.getId());
System.out.println("流程实例ID:" + hti.getProcessInstanceId());
System.out.println("班里人:" + hti.getAssignee());
System.out.println("创建时间:" + hti.getCreateTime());
System.out.println("结束时间:" + hti.getEndTime());
System.out.println("===========================");
}
return result;
}
15.转办
public Result transferAssignee(String taskId, String userCode) {
Result result = new Result();
taskService.setAssignee(taskId, userCode); //转办操作
taskService.setOwner(taskId, "总经理"); //如果想记录之前输入谁可以设置
return result;
}
16.签收
public Result claim(String taskId, String userId) {
taskService.claim(taskId, userId);
return null;
}
17.查看流程定义图片
public void image(HttpServletResponse response,
@RequestParam String processInstanceId) {
try {
List<String> list = processEngine.getRepositoryService()//
.getDeploymentResourceNames(processInstanceId);
//定义图片资源的名称
String resourceName = "";
if(list!=null && list.size()>0){
for(String name:list){
if(name.indexOf(".png")>=0){
resourceName = name;
}
}
}
//获取图片的输入流
InputStream in = processEngine.getRepositoryService()//
.getResourceAsStream(processInstanceId, resourceName);
if (in == null)
return;
response.setContentType("image/png");
BufferedImage image = ImageIO.read(in);
OutputStream out = response.getOutputStream();
ImageIO.write(image, "png", out);
in.close();
out.close();
} catch (Exception ex) {
log.error("查看流程图失败", ex);
}
}
以上为目前记录的一些可能用到的操作,后续有新的会继续补充