【springboot】与activiti7进行整合的工具类

  • 引入依赖
    【注意:由于会自动引入mybatis依赖,所以如果引入后启动项目报错,可把mybatis依赖排除。】
<!-- activiti 所需依赖 start -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta2</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-image-generator</artifactId>
            <version>7.1.0.M6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!-- activiti 所需依赖 end -->

  • application.yml配置
    【注意:activiti7配置信息,不要放在boostrap.yml 里面,我这边自测启动会报错。】
# Spring相关配置
spring:
  ##数据库连接信息
  datasource:
    # 数据源配置
    url: jdbc:mysql://127.0.0.1:3306/activiti2?useUnicode=true&characterEncoding=utf-8&useSSL=false&nullCatalogMeansCurrent=true
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  application:
    # 注册应用名
    name: actdemo
#    如果运行报错是 Could not set database schema on connection 可以先把activiti节点相关注解掉试试。
  activiti:
    # 自动建表  ACTIVITI 启用 activiti 必须要配置再 application.yml中
    database-schema: ACTIVITI
    database-schema-update: true
    history-level: full
    db-history-used: true
  jpa:
    show-sql: true

  • 使用前说明:
    1、我这里要提前说明,你需要懂得如何画流程图(epmn)文件,再用以下工具类会合适一些。因为你要懂得代理人(assign)、候选人(candidate)、流程变量、流程控制等名词。
    2:
    [流程定义]:就是导入了一个bpmn文件,算是定义了一个流程的结构。
    [流程实例]:根据流程定义创建出一个真实的流程数据,比如某员工创建了请假条。
    [任务]: 就是流程中的节点,该节点只允许存在一个负责人,但是可以存在多个候选人或者候选组。
    【流程部署】:就是把你的bpmn文件解析存到数据库中,相当于新增了一条请假单模板。
    【开启流程】:相当于你根据请假条模板创建了一条请假单,在创建方法( startProcessInstanceByKey )中就要指定接下来流程节点候选人(单个或多个)都有哪些。

  • 举例:

  • 在这里插入图片描述

  • 工具类:

package com.example.util;

import com.sun.istack.internal.NotNull;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntityImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.el.PropertyNotFoundException;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipInputStream;

/**
 * [描述]
 *@author Da.Pang
 */
@Component
public class Activiti7Util {
    /**
     * [描述]资源管理类
     */
    @Autowired
    private RepositoryService repositoryService;
    /**
     * 运行时管理类
     */
    @Autowired
    private RuntimeService runtimeService;
    /**
     * [描述] 任务管理类
     */
    @Autowired
    private TaskService taskService;
    /**
     * [描述] 历史数据管理类
     */
    @Autowired
    private HistoryService historyService;
    /**
     * [描述] 流程引擎管理类
     */
    @Autowired
    private ManagementService managementService;

    /**
     * [描述] 流程部署-- 上传文件进行部署
     * @param name:: 给部署起一个名字
     * @param file:上传的bpmn文件
     * @param bpmnResourceName: test.bpmn 文件名
     * @param imgFile: bpmn图片文件
     * @param imgResourceName: bpmn图片文件名
     */
    public Map<String, Object> importProcess(MultipartFile file ,MultipartFile imgFile, String name ,
                                    String bpmnResourceName , String imgResourceName) throws Exception{
        Resource resource = file.getResource();
        DeploymentBuilder name1 = repositoryService
                .createDeployment()
                .name(name);
        name1.addInputStream(bpmnResourceName, file.getInputStream());
        if (imgResourceName != null){
            name1.addInputStream(imgResourceName, imgFile.getInputStream());
        }
        Deployment deployment = name1.deploy();
        return getMap(deployment);
    }


    /**
     * [描述] 流程部署--将bpmn文件放在resources/process 文件夹中进行部署
     * @param name 部署时候可以起一个名字
     * @param bpmnName bpmn文件名[带文件后缀 .bpmn]
     * @param bpmnImgName bpmn图片名[带图片后缀]
     */
    public Map<String, Object> importProcessByResources(@NotNull String name , @NotNull String bpmnName , String bpmnImgName){
        DeploymentBuilder deployment = repositoryService.createDeployment();
        deployment.name(name);
        deployment.addClasspathResource("processes/"+bpmnName);
        if (bpmnImgName != null){
            deployment.addClasspathResource("processes/"+bpmnImgName);
        }
        //执行部署
        Deployment deploy = deployment.deploy();
       return getMap(deploy);
    }

    /**
     * [描述] 流程部署-- 通过zip包进行bpmn文件部署
     * @param zipPath: zip文件的路径 带[.zip] 后缀
     * @param name: 给部署起一个名字
     */
    public Map<String, Object> importProcessByZip(String zipPath , String name  ) throws FileNotFoundException {
        FileInputStream fileInputStream = new FileInputStream(zipPath);
        ZipInputStream stream = new ZipInputStream(fileInputStream);
        Deployment deploy = repositoryService.createDeployment()
                .addZipInputStream(stream)
                //act_re_procdef 表中的name
                .name(name)
                .deploy();
       return getMap(deploy);
    }

    private Map<String, Object> getMap(Deployment deploy) {
        Map<String, Object> map = new HashMap<>(3);
        System.out.println("部署ID:" + deploy.getId());
        System.out.println("部署Name:" + deploy.getName());
        System.out.println("部署时间:" + deploy.getDeploymentTime());
        map.put("deploymentId", deploy.getId());
        map.put("deploymentName", deploy.getName());
        map.put("deploymentTime", deploy.getDeploymentTime());
        return map;
    }


    /**
     * [描述] 查询流程定义集合【流程定义模板列表】
     * @param key bpmn文件中的 processId
     *            processId = null 则查全部模板
     */
    public List<Map<String, Object>> queryProcessDefinition(String key){
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        if (key != null){
            //根据指定key查出模板
            query.processDefinitionKey(key);
        }

        List<Map<String, Object>> result = new ArrayList<>();
        //List<processDefinitionDTO> result = new ArrayList<>();
        List<ProcessDefinition> list = query.list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println("流程定义id="+processDefinition.getId());
            System.out.println("流程定义名称="+processDefinition.getName());
            System.out.println("流程定义key="+processDefinition.getKey());
            System.out.println("流程定义版本="+processDefinition.getVersion());
            System.out.println("流程部署id="+processDefinition.getDeploymentId());
            Map<String, Object> map = new HashMap<>(5);
            map.put("deploymentId", processDefinition.getDeploymentId());
            map.put("processDefinitionId", processDefinition.getId());
            map.put("processDefinitionKey", processDefinition.getKey());
            map.put("processDefinitionName", processDefinition.getName());
            map.put("processDefinitionVersion", processDefinition.getVersion());
            result.add(map);
        }
        return result;
    }


    /**
     * [描述] 删除流程部署信息
     * @param deploymentId 流程部署id
     * @param cascade: true-连同已经存在的运行任务一起删除
     *                 false-不删除运行的任务
     *@author Da.Pang
     */
    public void deleteProcessDefinition(String deploymentId , boolean cascade)   {
        //传入 流程部署id【如果已经存在运行任务,则这样的删除会报错】
        //repositoryService.deleteDeployment(deploymentId);
        //即便已经存在运行的任务,会执行级联删除操作【将运行的任务一起删除】
        repositoryService.deleteDeployment(deploymentId, cascade);
        System.out.println("删除流程部署信息成功");
    }


    /**
     * [描述] 根据指定的bpmn的 processId 下载已经存在数据库中的文件
     * 需要 common-io.jar
     * @param key bpmn文件中的 processId
     * @param imgSavePath 需要把对应的图片文件保存的绝对路径【例:D:/bpmn/test-image.png】
     * @param bpmnSavePath 需要把对应的bpmn文件保存的绝对路径【例:D:/bpmn/test-bpmn.bpmn】
     */
    public void downDeployment(String key ,String imgSavePath,String bpmnSavePath) {
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
            //根据指定key查出模板
            query.processDefinitionKey(key);
        for (ProcessDefinition processDefinition : query.list()) {
            //    拿到deploymentId
            String deploymentId = processDefinition.getDeploymentId();
            //图片目录和名称
            String pngName = processDefinition.getDiagramResourceName();
            InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, pngName);
            String bpmnName = processDefinition.getResourceName();
            InputStream bpmnNameResourceAsStream = repositoryService.getResourceAsStream(deploymentId, bpmnName);
            File pngFile = new File(imgSavePath);
            File bpmnFile = new File(bpmnSavePath);
            FileOutputStream pngFileOutputStream = null;
            FileOutputStream bpmnFileOutputStream = null;
            try{
             pngFileOutputStream = new FileOutputStream(pngFile);
             bpmnFileOutputStream = new FileOutputStream(bpmnFile);
            IOUtils.copy(resourceAsStream, pngFileOutputStream);
            IOUtils.copy(bpmnNameResourceAsStream, bpmnFileOutputStream);
                }catch(Exception e){
                e.printStackTrace();
            }finally {
                //关闭流输入流
                try {
                    resourceAsStream.close();
                bpmnNameResourceAsStream.close();
                assert pngFileOutputStream != null;
                assert bpmnFileOutputStream != null;
                //关闭流输出流
                pngFileOutputStream.close();
                bpmnFileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
       System.out.println("操作成功");
    }

    /**
     * [描述] 开启一个流程实例
     * @param processDefinitionId 流程定义id
     * @param businessKey 可以绑定一个自定义的业务id
     * @param params:
     *              key:在bpmn文件中定义的变量占位符【例: ${userName}】
     *              value:对应的占位值 【例: 小明】
     *@author Da.Pang
     */
    public void startProcessInstanceByKey(String processDefinitionId, String businessKey , Map<String,Object> params ){
        // 根据流程定义ID启动流程
        ProcessInstance one = runtimeService.startProcessInstanceByKey(processDefinitionId, params);
        System.out.println("流程定义id:"+one.getProcessDefinitionId());
        System.out.println("流程实例id:"+one.getId());
        System.out.println("当前活动id:"+one.getActivityId());
        System.out.println("当前业务id:"+one.getBusinessKey());
        System.out.println(one.getProcessVariables());
        System.out.println("===============启动成功==================");
    }


    /**
     * [描述] 【如果某个任务设置了候选人】则可通过该方法查询候选人【根据人名查出 自己有哪些任务待拾取】
     *@author Da.Pang
     * @param key bpmn里面的id值
     * @param candidateUserName: 候选人名
     */
    public List<Map<String, Object>> taskListByCandidateUser( String key ,String candidateUserName){
        //获取 已经运行的任务列表
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(key).list();
        //List<TaskDTO> result = new ArrayList<>();
        List<Map<String, Object>> result = new ArrayList<>();
        // 根据传入的候选人名字 去查出哪些任务待办
        for (Task task : taskList) {
            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());
            //根据任务id 查出相应的候选人列表
            List<IdentityLink> linksForTask = taskService.getIdentityLinksForTask(task.getId());
            for (IdentityLink link : linksForTask) {
                System.out.println("候选人:"+link.getUserId());
                System.out.println("组id:"+link.getGroupId());
                System.out.println("候选类型:"+link.getType());
                //说明该任务的候选人之一 跟传入的参数相同 则该任务属于待办
                if (candidateUserName.equals(link.getUserId())){
                    List<String> collect = linksForTask.stream().map(IdentityLink::getUserId).collect(Collectors.toList());
                    Map<String, Object> map = new HashMap<>(8);
                    map.put("taskId", task.getId());
                    map.put("taskName", task.getName());
                    map.put("createTime", task.getCreateTime());
                    map.put("taskAssignee", task.getAssignee());
                    map.put("processInstanceId", task.getProcessInstanceId());
                    map.put("candidateList", collect);
                    map.put("candidateType", link.getType());
                    result.add(map);
                    break;
                }
            }
        }
        return result;
    }


    /**
     * [描述] 【如果某个任务设置了候选人】 某个负责人进行拾取任务【通过任务id和人名 开始拾取任务】
     *@author Da.Pang
     * @param taskId: 任务id
     * @param candidateUserName 候选人名
     * @return true-拾取成功 false=拾取失败
     */
    public boolean claimTask( String taskId , String candidateUserName ){
        //根据条件 查出任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                //由于这里 会调用Spring Security 框架 所有不采用这个方式
                //.taskCandidateUser(candidateUserName)
                .singleResult();
        //能查到任务并且 传入参数也符合候选人 才能进行拾取
        if (task != null && isCandidate(taskId, candidateUserName)){
            //进行拾取操作 其实就是把指定任务的assignee设置对应的负责人名
            taskService.claim(task.getId(), candidateUserName);
            System.out.println("拾取任务成功,往下可以继续完成改任务");
            return true;
        }
        System.out.println("【error】拾取任务失败,没有查到对应任务");
        return false;
    }

    /**
     * [描述] 判断指定任务的候选人名单中是否有: candidateUserName
     * @return true:是候选人  false:不是候选人
     */
    private boolean isCandidate(String taskId , String candidateUserName ){
        for (IdentityLink link : taskService.getIdentityLinksForTask(taskId)) {
            if (candidateUserName.equals(link.getUserId())){
                return true;
            }
        }
        return false;
    }

    /**
     * [描述]【如果某个任务设置了候选人】 负责人已经拾取某个任务以后 打算再归还回去
     *@author Da.Pang
     * @param taskId: 任务id
     * @param candidateUserName 候选人名
     */
    public boolean claimTaskReturn( String taskId , String candidateUserName ){
        //根据条件 查出任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateUser(candidateUserName)
                .singleResult();
        if (task != null){
            //归还操作 其实就是把该任务的 assignee 设置成null
            taskService.setAssignee(task.getId(), null);
           System.out.println("归还任务成功");
           return true;
        }
        System.out.println("【error】归还任务失败,没有查到任务");
        return false;
    }


    /**
     * [描述] 【如果某个任务设置了候选人】某个任务虽然是自己的  但是可以交给其他人进行完成
     *@author Da.Pang
     * @param taskId: 任务id
     * @param candidateUserName 候选人名
     * @param assigneeName: 交接人
     */
    public boolean taskHandover(String taskId , String candidateUserName, String  assigneeName  ){
        //根据条件 查出任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateUser(candidateUserName)
                .singleResult();
        //交接操作 这个任务是自己虽然是候选人 但是 可以直接把这个任务交接给别人进行完成
        if (task != null){
            taskService.setAssignee(task.getId(), assigneeName);
            System.out.println("交接成功");
            return true;
        }
        System.out.println("【error】交接失败,没有查到任务");
        return false;
    }


    /**
     * [描述] 根据名字 查询个人待执行的任务【已经把任务拾取了】【带分页】
     * @param taskAssignName 人名【例:班长、经理、总经理等...】
     * @param key  bpmn文件中的processId
     * @param firstResult  当前页【默认从0开始】
     * @param maxResults  页长
     */
    public  List<Map<String, Object> > taskListByMy(String taskAssignName , String key , Integer firstResult , Integer maxResults){
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(taskAssignName)
                .listPage(firstResult, maxResults);
        List<Map<String, Object> > result = new ArrayList<>();
        for (Task task : list) {
            System.out.println("流程定义id="+task.getProcessDefinitionId());
            System.out.println("任务id="+task.getId());
            System.out.println("任务负责人="+task.getAssignee());
            System.out.println("任务名称="+task.getName());
            Map<String, Object> taskMap = new HashMap<>(5);
            taskMap.put("taskId", task.getId());
            taskMap.put("taskName", task.getName());
            taskMap.put("createTime", task.getCreateTime());
            taskMap.put("taskAssignee", task.getAssignee());
            taskMap.put("processInstanceId", task.getProcessInstanceId());
            result.add(taskMap);
        }
        return result;
    }


    /**
     * [描述] 完成个人任务
     * @param taskAssignName: 任务代理人
     * @param taskId: 任务id
     * params: 流程连接线上的变量
     * 【例】假如流程线上面有一个变量名 ${audit=='通过'}
     * 则调用时候:params.put("audit","通过");
     * 这里执行时,会判断控制线的变量 从而控制流程走向
     */
    public boolean completeTask( String taskAssignName , String taskId , Map<String, Object> params){
        try{
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .taskAssignee(taskAssignName)
                    .singleResult();
            if (task == null){
                System.out.println("【error】 说明根据任务id和人名 无法查到待办的指定任务");
                return false;
            }
            taskService.complete(taskId ,params);
            System.out.println("任务完成成功");
            return true;
            }catch(ActivitiException ee){
            ee.printStackTrace();
            System.out.println( "【error】流程线上已经绑定变量了:"+ee.getMessage());
            return false;
            }catch(Exception e){
            e.printStackTrace();
            System.out.println("【error】 执行报错: "+e.getMessage());
             return false;
        }
    }

    /**
     * [描述] 先执行拾取任务,再进行完成任务。
     *@author Da.Pang
     */
    public boolean claimTaskAndCompleteTask(String taskId, String candidateUserName , Map<String, Object> params){
        if (this.claimTask(taskId,candidateUserName)){
            this.completeTask(candidateUserName, taskId,params);
            return true;
        };
        System.out.println( "【error】没有可以拾取的任务");
        return false;
    }


    /**
     * [描述] 根据相应的条件 查出历史的任务信息
     *@author Da.Pang
     * @param processDefinitionId: 流程定义id
     * @param processInstanceId: 流程实例id
     * @param assigneeName: 代理人名
     */
    public  List<HistoricActivityInstance> historicActivityInstanceList(String processDefinitionId , String processInstanceId,String assigneeName ){
        //例子:查询 act_hi_actinst 表中数据
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
        if (processDefinitionId != null){
            //查询条件: 根据流程定义id 拿到数据
            instanceQuery.processDefinitionId(processDefinitionId);
        }
        if (processInstanceId != null){
            //查询条件: 根据流程实例id 拿到数据
            instanceQuery.processInstanceId(processInstanceId);
        }
        if (assigneeName != null){
            instanceQuery.taskAssignee(assigneeName);
        }
        List<HistoricActivityInstance> list = instanceQuery.list();
        //总数
        long count = instanceQuery.count();
        for (HistoricActivityInstance instance : list) {
            System.out.println(instance.toString());
        }
        return list;
    }


    /**
     * [描述]  通过流程定义id --》 [挂起【暂停】] 或 [激活【启动】] 全部流程实例的执行
     *@author Da.Pang
     */
    public void suspendAllProcessInstance( String key ){
        //通过指定的key 获取单个流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).singleResult();
        //判断指定的流程定义 是否挂起 true=挂起  false=激活
        boolean suspended = processDefinition.isSuspended();
        //拿到流程定义id
        String processDefinitionId = processDefinition.getId();
        if (suspended){
            //说明原来是挂起的 则可以对流程定义和旗下的所有流程实例进行激活操作
            //    参数说明:processDefinitionId=流程定义id 、 activateProcessInstances=挂起或者激活、activationDate=执行事件
            repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
            System.out.println("对流程定义id为"+processDefinitionId+",进行[激活]操作");
        }else{
            // 说明原来是激活的 则可以对流程定义和旗下的所有流程实例进行挂起操作
            repositoryService.activateProcessDefinitionById(processDefinitionId, false, null);
            System.out.println("对流程定义id为"+processDefinitionId+",进行[挂起]操作");
        }
       System.out.println("流程定义"+processDefinition.getName()+"已经操作成功【包括关联的所有实例】");
    }


    /**
     * [描述]  针对某一个流程实例进行【挂起】或【激活】操作
     *@author Da.Pang
     */
    public void suspendProcessInstanceByProcessInstanceId( String processInstanceId ){
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //原来是挂起的
        if (instance.isSuspended()){
            runtimeService.activateProcessInstanceById(instance.getId());
            System.out.println("流程实例id="+instance.getId()+",已激活");
        }else{
            runtimeService.suspendProcessInstanceById(instance.getId());
            System.out.println("流程实例id="+instance.getId()+",已挂起");
        }
        System.out.println("单个流程实例:"+instance.getName()+",已经操作成功");
    }


    /**
     * [描述] 根据流程实例id【未完成】的高亮图
     *@author Da.Pang
     */
    public void xx(@NotNull String processInstanceId, HttpServletResponse response)
            throws IOException {
        ExecutionEntity pi = (ExecutionEntity) runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        if (pi == null) {
        //pi 如果为null  说明指定实例已经完成。可以从历史汇总查出来。
            xx2(processInstanceId, response);
            return;
        }
        ProcessDefinitionEntity pde = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(pi.getProcessDefinitionId());
        List<String> highLightedActivities = getHighLightedActivities(processInstanceId);
        List<String> highLightedFlows = runtimeService.getActiveActivityIds(processInstanceId);
        if (pde != null && pde.isGraphicalNotationDefined()) {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(pde.getId());
            ProcessDiagramGenerator ge = new DefaultProcessDiagramGenerator();
            InputStream resource = getResource(highLightedActivities, highLightedFlows, bpmnModel, ge);
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = resource.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
        } else {
            throw new ActivitiException("Process instance with id "
                    + processInstanceId + " has no graphic description");
        }
    }

    /**
     * [描述] 根据流程实例id【完成】的高亮图
     *@author Da.Pang
     */
    private void xx2(String processInstanceId, HttpServletResponse response)throws IOException {
        HistoricProcessInstanceEntityImpl pi = (HistoricProcessInstanceEntityImpl)historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        if (pi == null){
            throw new ActivitiObjectNotFoundException(
                    "Process instance with id" + processInstanceId
                            + " could not be found", ProcessInstance.class);
        }
        ProcessDefinitionEntity pde = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(pi.getProcessDefinitionId());
        List<String> highLightedActivities = getHighLightedActivities(processInstanceId);
        if (pde != null && pde.isGraphicalNotationDefined()) {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(pde.getId());
            ProcessDiagramGenerator ge = new DefaultProcessDiagramGenerator();
            List<String> highLightedFlows = historyService.getHistoricIdentityLinksForProcessInstance(processInstanceId).stream()
                                    .map(HistoricIdentityLink::getTaskId).collect(Collectors.toList());
            InputStream resource = getResource(highLightedActivities, highLightedFlows, bpmnModel, ge);
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = resource.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
        } else {
            throw new ActivitiException("Process instance with id "
                    + processInstanceId + " has no graphic description");
        }
    }


    private List<String> getHighLightedActivities(@NotNull String processInstanceId) {
        List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId).list();
        return highLightedActivitList.stream().map(HistoricActivityInstance::getActivityId).collect(Collectors.toList());
    }
    private InputStream getResource(List<String> highLightedActivities, List<String> highLightedFlows, BpmnModel bpmnModel, ProcessDiagramGenerator ge) {
        return ge.generateDiagram(bpmnModel, highLightedActivities,
                highLightedFlows,
                "宋体", "宋体", null, false);
    }

}

  • 整个工具类有很多方法,但用得到的基本就是一部分:

/**
 * [描述]
 *@author Da.Pang
 */
@Controller
@RequestMapping("/act")
public class ActivityController {
    @Resource
    private Activiti7Util util;

    /**
     * [描述] bpmn文件中的主id
     */
    public static String bpmnProcessId = "Process_test";
    public static Map<String, String> map = new HashMap<>();
    public static String assigneeName = "小明";

    List<String> banzhangList = Arrays.asList("小黑班长","小白班长");
    List<String> teacherList = Arrays.asList("老师A","老师B");
    List<String> fuList = Arrays.asList("小粉副校长","小红副校长");
    List<String> zhengList = Arrays.asList("小绿正校长","小蓝正校长");


    /**
    * [描述] 部署bpmn文件
    *@author Da.Pang
    */
   @RequestMapping("/bushu")
   @ResponseBody
   public Object bushu( @RequestParam Map<String, Object> params ){
       String name = "请假条";
       String bpmnName = "qingjia.bpmn";
       String bpmnImgName = "qingjia.svg";
       Map<String, Object> deployment = util.importProcessByResources(name, bpmnName, bpmnImgName);
       return deployment;
   }

    /**
     * [描述] 启动一个流程实例
     *@author Da.Pang
     */
    @RequestMapping("/kaishi")
    @ResponseBody
    public Object kaishi(String applyUserName){

        Map<String, Object> params = new HashMap<>();
        params.put("userName", applyUserName);
        params.put("banzhangList", banzhangList);
        params.put("teacherList", teacherList);
        params.put("fuList", fuList);
        params.put("zhengList", zhengList);

        //TODO 这里可加入业务表 并获得新增的业务id  传入 businessKey
        String businessKey = "这里是业务id";
        util.startProcessInstanceByKey(bpmnProcessId, businessKey, params);
        List<Map<String, Object>> tasks = util.taskListByMy(assigneeName, bpmnProcessId, 0, 100);
        for (Map<String, Object> task : tasks) {
            String taskId = (String) task.get("taskId");
            //开始一个流程 就先完成自己的任务
            util.completeTask(assigneeName , taskId,null);
        }
        return "success";
    }

    /**
     * 这里传入某个候选人 获取自己的待办任务
     *@author Da.Pang
     */
    @RequestMapping("/shiquList")
    @ResponseBody
    public Object shiquList( @RequestParam Map<String, Object> params ){
        String candidateUserName = "SYSTEM";
        return util.taskListByCandidateUser(bpmnProcessId, candidateUserName);
    }



    /**
     * [描述] 拾取任务,并操作任务是否通过
     *@author Da.Pang
     */
    @RequestMapping("/tongguo")
    @ResponseBody
    public Object tongguo( @RequestParam Map<String, Object> params ){
        String taskId = "";
        params.put("roomCheck", 1);
        String candidateUserName = "SYSTEM";
        return  util.claimTaskAndCompleteTask(candidateUserName, taskId, params);
    }
    /**
     * [描述] 查已经操作过的任务、历史信息
     *@author Da.Pang
     */
    @RequestMapping("/lishi")
    @ResponseBody
    public Object historicActivityInstanceList( @RequestParam Map<String, Object> params ){
        String definitionId = "resourcesOccupy3:2:bb047ad5-9ecd-11ec-a39b-080058000005";
        String instanceId = null;
        String assigneeName = "";
        return  util.historicActivityInstanceList(definitionId, instanceId , assigneeName);
    }

}

demo地址

### 回答1: Activiti 7是一个工作流引擎,可以帮助您在应用程序中管理业务流程。Spring Boot是一个快速构建企业级应用程序的框架,因此,在Spring Boot整合Activiti 7是非常有用的。 整合步骤: 1. 在pom.xml中添加Activiti 7的依赖。 2. 配置Activiti数据源。 3. 在Spring Boot启动类中配置Activiti。 4. 创建Activiti配置类并使用@EnableProcessEngine注解启用流程引擎。 5. 在应用程序中部署工作流。 通过整合Activiti 7,您可以在Spring Boot应用程序中简化工作流管理,并且可以使用Activiti提供的强大功能来实现业务流程管理。 ### 回答2: Spring Boot是一种轻量级的Java开发框架,它用于简化开发过程和部署过程。Activiti是一个流程引擎框架,可用于实现和管理业务流程。Spring BootActiviti可以很好地结合在一起,以实现业务流程的自动化管理。 在整合Spring BootActiviti之前,首先需要在pom.xml文件中添加Activiti的依赖。然后,配置数据库连接,用于存储Activiti的运行数据。接下来,创建一个Activiti配置类,用于配置Activiti的相关参数,例如数据库连接等。在该配置类中,需要使用@EnableProcessApplication注解来启用Activiti的支持。 然后,可以创建业务流程的定义文件(BPMN文件),定义流程的节点、流转条件等。通过编写Java代码,可以使用Activiti提供的API来启动、暂停、终止等流程实例的操作。还可以实现流程的任务分配、任务处理以及流程实例的查询等功能。 在Spring Boot中,可以使用RestController注解来创建Web服务来与Activiti进行交互。通过编写相应的Controller方法,可以实现对流程实例、任务等信息的获取和处理。例如,可以创建一个启动流程的接口,通过调用Activiti的API来启动指定的流程实例。还可以创建一个查询任务的接口,通过调用Activiti的API来获取指定用户的待处理任务列表。 总之,通过整合Spring BootActiviti,可以快速搭建一个灵活、可扩展的业务流程管理系统。Spring Boot提供了简化的开发和部署过程,而Activiti提供了强大的流程管理功能。结合起来,可以提高开发效率,简化业务流程的管理和操作。 ### 回答3: Spring Boot是一个用于快速构建基于Spring框架的应用程序的框架,而Activiti是一个轻量级的开源工作流引擎。Spring BootActiviti可以很好地整合在一起,以实现更高效的工作流处理。 在Spring Boot中,可以通过使用Spring Boot Starter来快速集成Activiti。只需要在项目的pom.xml文件中添加相关的依赖,并在配置文件中配置Activiti的相关属性,就可以使用Activiti来管理工作流。此外,Spring Boot还提供了一些自动配置的功能,可以简化Activiti的配置和使用过程。 在整合Activiti之后,我们可以使用Activiti的各种功能来管理和运行工作流。可以定义流程模型,包括流程定义、任务、网关等,以及组织流程中的各个活动。可以使用Activiti提供的API来启动、暂停、终止和查询流程实例,并管理流程中的任务、变量、历史记录等。同时,还可以使用Activiti提供的各种监听器来实现工作流的自定义操作,例如发送邮件、生成报表等。 整合Spring BootActiviti的好处在于,可以快速搭建一个完整的工作流管理系统,提高工作效率和质量。Spring Boot提供了丰富的开发工具和框架支持,使得使用Activiti变得更加简单和方便。通过利用Spring Boot的自动配置功能,可以减少繁琐的配置工作,更快地启动和部署工作流。同时,Spring Boot还提供了一些监控和管理工具,可以方便地监控和管理工作流的运行情况。 总之,Spring BootActiviti整合为我们提供了一个强大且易于使用的工作流引擎,可以大大简化工作流的开发和管理过程。通过合理利用Spring BootActiviti的各种功能,可以实现更高效、更灵活、更可靠的工作流处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值