springboot2.X集成activiti6.X记录(三)_runtimeservice.createprocessinstancequery() 过滤掉指定流-程序员宅基地

技术标签: activiti  

这里主要记录一下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 [email protected]
 * @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 [email protected]
 * @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);
        }
    }

以上为目前记录的一些可能用到的操作,后续有新的会继续补充

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/l_bu_ting_hua/article/details/86636108

智能推荐

已知num为无符号十进制整数,请写一非递归算法,该算法输出num对应的r进制的各位数字。要求算法中用到的栈采用线性链表存储结构(1<r<10)。-程序员宅基地

文章浏览阅读74次。思路:num%r得到末位r进制数,num/r得到num去掉末位r进制数后的数字。得到的末位r进制数采用头插法插入链表中,更新num的值,循环计算,直到num为0,最后输出链表。//重置,s指针与头指针指向同一处。//更新num的值,至num为0退出循环。//末位r进制数存入s数据域中。//头插法插入链表中(无头结点)//定义头指针为空,s指针。= NULL) //s不为空,输出链表,栈先入后出。

开始报名!CW32开发者扶持计划正式进行,将助力中国的大学教育及人才培养_cw32开发者扶持计划申请-程序员宅基地

文章浏览阅读176次。武汉芯源半导体积极参与推动中国的大学教育改革以及注重电子行业的人才培养,建立以企业为主体、市场为导向、产学研深度融合的技术创新体系。2023年3月,武汉芯源半导体开发者扶持计划正式开始进行,以打造更为丰富的CW32生态社区。_cw32开发者扶持计划申请

希捷硬盘开机不识别,进入系统后自动扫描硬件以识别显示_st2000dm001不认盘-程序员宅基地

文章浏览阅读5.7k次。2014年底买的一块2TB希捷机械硬盘ST2000DM001-1ER164,用了两年更换了主板、CPU等,后来出现开机不识别的情况,具体表现为:关机后开机,找不到硬盘,就进入BIOS了,只要在BIOS状态下待机半分钟左右再重启,硬盘就会出现。进入系统后,重启(这个过程中主板对硬盘始终处于供电状态),也不会出现不识别硬盘的现象。就好像是硬盘或主板上某个电容坏了一样,刚开始给硬盘通电的N秒钟内电容未能..._st2000dm001不认盘

ADO.NET包含主要对象以及其作用-程序员宅基地

文章浏览阅读1.5k次。ADO.NET的数据源不单单是DB,也可以是XML、ExcelADO.NET连接数据源有两种交互模式:连接模式和断开模式两个对应的组件:数据提供程序(数据提供者)&DataSetSqlConnectionStringBuilder——连接字符串Connection对象用于开启程序和数据库之间的连接public SqlConnection c..._列举ado.net在操作数据库时,常用的对象及作用

Android 自定义对话框不能铺满全屏_android dialog宽度不铺满-程序员宅基地

文章浏览阅读113次。【代码】Android 自定义对话框不能铺满全屏。_android dialog宽度不铺满

Redis的主从集群与哨兵模式_redis的主从和哨兵集群-程序员宅基地

文章浏览阅读331次。Redis的主从集群与哨兵模式Redis的主从模式全量同步增量同步Redis主从同步策略流程redis主从部署环境哨兵模式原理哨兵模式概述哨兵模式的作用哨兵模式项目部署Redis的主从模式1、Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。2、为了分担读压力,Redis支持主从复制,保证主数据库的数据内容和从数据库的内容完全一致。3、Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。全量同步Redis全量复制一般发_redis的主从和哨兵集群

随便推点

mysql utf-8的作用_为什么不建议在MySQL中使用UTF-8-程序员宅基地

文章浏览阅读116次。作者:brightwang原文:https://www.jianshu.com/p/ab9aa8d4df7d最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value: ‘😃 我用的是UTF-8编码的客户端,服务器也是UTF-8编码的,数据库也是,就连要保存的这个字符串“????..._mysql utf8的作用

MATLAB中对多张图片进行对比画图操作(包括RGB直方图、高斯+USM锐化后的图、HSV空间分量图及均衡化后的图)_matlab图像比较-程序员宅基地

文章浏览阅读278次。毕业这么久了,最近闲来准备把毕设过程中的代码整理公开一下,所有代码其实都是网上找的,但都是经过调试能跑通的,希望对需要的人有用。PS:里边很多注释不讲什么意思了,能看懂的自然能看懂。_matlab图像比较

16.libgdx根据配置文件生成布局(未完)-程序员宅基地

文章浏览阅读73次。思路:  screen分为普通和复杂两种,普通的功能大部分是页面跳转以及简单的crud数据,复杂的单独弄出来  跳转普通的screen,直接根据配置文件调整设置<layouts> <loyout screenId="0" bg="bg_start" name="start" defaultWinId="" bgm="" remark=""> ..._libgdx ui 布局

playwright-python 处理Text input、Checkboxs 和 radio buttons(三)_playwright checkbox-程序员宅基地

文章浏览阅读3k次,点赞2次,收藏13次。playwright-python 处理Text input和Checkboxs 和 radio buttonsText input输入框输入元素,直接用fill方法即可,支持 ,,[contenteditable] 和<label>这些标签,如下代码:page.fill('#name', 'Peter');# 日期输入page.fill('#date', '2020-02-02')# 时间输入page.fill('#time', '13-15')# 本地日期时间输入p_playwright checkbox

windows10使用Cygwin64安装PHP Swoole扩展_win10 php 安装swoole-程序员宅基地

文章浏览阅读596次,点赞5次,收藏6次。这是我看到最最详细的安装说明文章了,必须要给赞!学习了,也配置了,成功的一批!真不知道还有什么可补充的了,在此做个推广,喜欢的小伙伴,走起!_win10 php 安装swoole

angular2里引入flexible.js(rem的布局)_angular 使用rem-程序员宅基地

文章浏览阅读1k次。今天想实现页面的自适应,本来用的是栅格,但效果不理想,就想起了rem布局。以前使用rem布局,都是在原生html里,还没在框架里使用过,百度没百度出来,就自己琢磨,不知道方法规范不规范,反正成功了,操作如下:1、下载flexible.js2、引入到angular项目里3、根据自己的需要修改细节3.1、在flexible.js里修改每份的像素,3.2、引入cssrem插件,在设置里设..._angular 使用rem

推荐文章

热门文章

相关标签