springboot整合activiti测试项目

springboot整合activiti测试项目

最近学习了一下springboot整合activiti工作流框架,遇到了一些坑,写一篇文章记录下,写了个入门小程序。
首先用我自己的理解,白话的解释一下activiti框架,在使用之前,我们要搞清楚两个概念,一个是流程,一个是任务。接下来按照我的操作流程会说到这两个概念。
step1
新建一个springboot项目,导入相关依赖,我的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.yhz</groupId>
    <artifactId>activiti-springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>activiti-springboot</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>1.5.2</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>janino</artifactId>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>5.22.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

activiti是有自己的数据库的,所以我们需要初始化数据库,关于数据库各个表的用途联系不做叙述,百度一大堆,直接贴代码,我这里是写在一个测试类的里的,如果以后涉及到项目开发,可以把这个数据库初始化操作放到项目启动时去判断执行一下(这个以后准备试试),代码如下:

package org.yhz.activitispringboot;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.junit.Test;

/**
 * @author yaohongzhen
 * @date 2020/6/18 11:21
 * @description
 */
public class ActivitiEnviroment {
    @Test
    public void test_createDatabase() {
        // 创建流程引擎配置信息对象
        ProcessEngineConfiguration pec = ProcessEngineConfiguration
                .createStandaloneProcessEngineConfiguration();
        // 设置数据库的类型
        pec.setDatabaseType("mysql");
        // 设置创建数据库的方式
//        ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE(true);//如果没有数据库表就会创建数据库表,有的话就修改表结构.
        // ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE(false): 不会创建数据库表
        // ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP(create-drop): 先创建、再删除.
        pec.setDatabaseSchemaUpdate("true");
        // 设置数据库驱动
        pec.setJdbcDriver("com.mysql.jdbc.Driver");
        // 设置jdbcURL
        pec.setJdbcUrl("jdbc:mysql://localhost:3306/test??useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
        // 设置用户名
        pec.setJdbcUsername("root");
        // 设置密码

        pec.setJdbcPassword("root");

//        pec.setJdbcPassword("XXXX");

        // 构建流程引擎对象
        ProcessEngine pe = pec.buildProcessEngine(); // 调用访方法才会创建数据表
        // 调用close方法时,才会删除
        pe.close();
    }
}

初始化完数据之后,我们需要接触到一第一个概念,流程。
关于流程,我用的是idea,首先我们需要插件库去下载actiBPM插件,我的idea版本是2019.3,idea升级之后不知道为什么取消了这个插件,所以如果你搜不到的话要去idea官网插件库搜错下载这个jar包,然后通过本地导入的方式引入,这里不做赘述,当我们装好这个插件就可以创建bpmn文件,这个类似于流程图,我这里画的是最简单的流程图,模拟了一个审批流程的过程,我画的bpmn文件如下:
在这里插入图片描述
创建了bpmn文件之后,我们需要部署这个流程,部署流程的方法如下:

  @Value("${activiti.resource.path}")
  private String resourcePath;
    
  /**
     * 部署一个流程
     *
     * @param resourceName
     */
    public void deploy(String resourceName) {
        try {
            Deployment deploy = repositoryService.createDeployment().addClasspathResource(resourcePath + resourceName).deploy();
            log.info("流程部署完毕,流程id:{}", deploy.getId());
        } catch (Exception e) {
            log.error("部署失败:{}", e.getMessage());
        }
    }

当我们部署了这个流程之后,我们在数据库可以看到这个流程的部署信息,表名在红色框里。
在这里插入图片描述
流程部署完毕后,我们可以理解为我们有了个流程模板,我们可以用这个模板去跑一个流程实例,首先写了个查询所有定义流程(也就是流程模板)的方法:

    /**
     * 获取所有部署流程信息
     *
     * @return
     */
    public List<ProcessVo> processList() {
        List<ProcessVo> processVoList = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionId().desc().list().stream().map(processDefinition -> {
            ProcessVo processVo = new ProcessVo();
            processVo.setId(processDefinition.getId());
            processVo.setName(processDefinition.getName());
            processVo.setKey(processDefinition.getKey());
            processVo.setVersion(processDefinition.getVersion());
            processVo.setResourceName(processDefinition.getResourceName());
            processVo.setDiagramResourceName(processDefinition.getDiagramResourceName());
            processVo.setDeploymentId(processDefinition.getDeploymentId());
            return processVo;
        }).collect(Collectors.toList());
        return processVoList;
    }

我们可以获取所有部署过的流程模板,我们可以用他的key去开启一个流程,开启流程的方法如下:

    /**
     * 启动一个流程
     *
     * @param key
     */
    public void start(String key) {
        try {
            ProcessInstance processInstance = this.runtimeService.startProcessInstanceById(key);
            log.info("流程发起成功,流程id:{}", processInstance.getId());
        } catch (Exception e) {
            log.error("启动失败:{}", e.getMessage());
        }
    }

当我们开启了一个流程,流程就会进入我们画的流程图的第一个节点,这个流程相当于这个节点来说就是一个任务,我们可以流程定义id获得这个流程下所有在执行的任务:

  /**
     * 获取流程下的任务
     *
     * @param key
     * @return
     */
    public List<TaskVO> taskList(String key) {
        List<Task> list = taskService//与正在执行的任务管理相关的Service
                .createTaskQuery()//创建任务查询对象
                .processDefinitionId(key)//使用流程定义ID查询
                .orderByTaskCreateTime().desc()//使用创建时间的升序排列
                .list();//返回列表

        List<TaskVO> taskVOList = null;

        if (list != null && list.size() > 0) {
            taskVOList = list.stream().map(task -> {
                TaskVO taskVO = new TaskVO();
                taskVO.setId(task.getId());
                taskVO.setName(task.getName());
                taskVO.setAssignee(task.getAssignee());
                taskVO.setCreateTime(task.getCreateTime());
                taskVO.setExecutionId(task.getExecutionId());
                taskVO.setProcessDefinitionId(task.getProcessDefinitionId());
                taskVO.setProcessInstanceId(task.getProcessInstanceId());
                Map<String, Object> variables = taskService.getVariables(task.getId());
                taskVO.setResult((String) variables.get("审批结果"));
                taskVO.setMsg((String) variables.get("审批备注"));
                return taskVO;
            }).collect(Collectors.toList());
        }
        return taskVOList;
    }

当我们想把这个节点的任务完成之后,可以通过任务id去完成这个任务:

    /**
     * 完成一个流程
     *
     * @param taskId
     * @throws Exception
     */
    public void complete(String taskId, String result, String suggestion) {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("money", result);
        try {
            taskService.complete(taskId, variables);
        } catch (Exception e) {
            log.error("完成流程失败:" + e.getMessage());
        }
    }

当我们需要知道这个某个启动的流程结束没有或者走到哪个节点,可以用这个方法:

    /**
     * 判断流程是否结束
     *
     * @param processInstanceId
     */
    public boolean isProcessEnd(String processInstanceId) {
        ProcessInstance pi = runtimeService//表示正在执行的流程实例和执行对象
                .createProcessInstanceQuery()//创建流程实例查询
                .processInstanceId(processInstanceId)//使用流程实例ID查询
                .singleResult();

        if (pi == null) {
            log.debug("流程已经结束");
            return true;
        } else {
            log.debug("流程没有结束");
            return false;
        }
    }

    /**
     * 获取流程当前所在节点
     *
     * @param instanceId
     * @return
     */
    public String getCurrectActivity(String instanceId) {
        Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
        log.info("name==>" + task.getName());
        return task.getName();
    }

到此,一些基本的activiti操作就结束了,下一篇我会写关于activiti网关的使用。
附上完整的代码:

package org.yhz.activitispringboot.service;

import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.yhz.activitispringboot.vo.ProcessVo;
import org.yhz.activitispringboot.vo.TaskVO;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yaohongzhen
 * @date 2020/6/18 13:20
 * @description
 */
@Service
@Slf4j
public class ActivitiService {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Value("${activiti.resource.path}")
    private String resourcePath;

    /**
     * 部署一个流程
     *
     * @param resourceName
     */
    public void deploy(String resourceName) {
        try {
            Deployment deploy = repositoryService.createDeployment().addClasspathResource(resourcePath + resourceName).deploy();
            log.info("流程部署完毕,流程id:{}", deploy.getId());
        } catch (Exception e) {
            log.error("部署失败:{}", e.getMessage());
        }
    }

    /**
     * 获取所有部署流程信息
     *
     * @return
     */
    public List<ProcessVo> processList() {
        List<ProcessVo> processVoList = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionId().desc().list().stream().map(processDefinition -> {
            ProcessVo processVo = new ProcessVo();
            processVo.setId(processDefinition.getId());
            processVo.setName(processDefinition.getName());
            processVo.setKey(processDefinition.getKey());
            processVo.setVersion(processDefinition.getVersion());
            processVo.setResourceName(processDefinition.getResourceName());
            processVo.setDiagramResourceName(processDefinition.getDiagramResourceName());
            processVo.setDeploymentId(processDefinition.getDeploymentId());
            return processVo;
        }).collect(Collectors.toList());
        return processVoList;
    }

    /**
     * 启动一个流程
     *
     * @param key
     */
    public void start(String key) {
        try {
            ProcessInstance processInstance = this.runtimeService.startProcessInstanceById(key);
            log.info("流程发起成功,流程id:{}", processInstance.getId());
        } catch (Exception e) {
            log.error("启动失败:{}", e.getMessage());
        }
    }

    /**
     * 获取流程下的任务
     *
     * @param key
     * @return
     */
    public List<TaskVO> taskList(String key) {
        List<Task> list = taskService//与正在执行的任务管理相关的Service
                .createTaskQuery()//创建任务查询对象
                .processDefinitionId(key)//使用流程定义ID查询
                .orderByTaskCreateTime().desc()//使用创建时间的升序排列
                .list();//返回列表

        List<TaskVO> taskVOList = null;

        if (list != null && list.size() > 0) {
            taskVOList = list.stream().map(task -> {
                TaskVO taskVO = new TaskVO();
                taskVO.setId(task.getId());
                taskVO.setName(task.getName());
                taskVO.setAssignee(task.getAssignee());
                taskVO.setCreateTime(task.getCreateTime());
                taskVO.setExecutionId(task.getExecutionId());
                taskVO.setProcessDefinitionId(task.getProcessDefinitionId());
                taskVO.setProcessInstanceId(task.getProcessInstanceId());
                Map<String, Object> variables = taskService.getVariables(task.getId());
                taskVO.setResult((String) variables.get("审批结果"));
                taskVO.setMsg((String) variables.get("审批备注"));
                return taskVO;
            }).collect(Collectors.toList());
        }
        return taskVOList;
    }

    /**
     * 完成一个流程
     *
     * @param taskId
     * @throws Exception
     */
    public void complete(String taskId, String result, String suggestion) {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("money", result);
        try {
            taskService.complete(taskId, variables);
        } catch (Exception e) {
            log.error("完成流程失败:" + e.getMessage());
        }
    }

    /**
     * 判断流程是否结束
     *
     * @param processInstanceId
     */
    public boolean isProcessEnd(String processInstanceId) {
        ProcessInstance pi = runtimeService//表示正在执行的流程实例和执行对象
                .createProcessInstanceQuery()//创建流程实例查询
                .processInstanceId(processInstanceId)//使用流程实例ID查询
                .singleResult();

        if (pi == null) {
            log.debug("流程已经结束");
            return true;
        } else {
            log.debug("流程没有结束");
            return false;
        }
    }

    /**
     * 获取流程当前所在节点
     *
     * @param instanceId
     * @return
     */
    public String getCurrectActivity(String instanceId) {
        Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
        log.info("name==>" + task.getName());
        return task.getName();
    }
}

package org.yhz.activitispringboot.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.yhz.activitispringboot.service.ActivitiService;
import org.yhz.activitispringboot.vo.ResultBean;

/**
 * @author yaohongzhen
 * @date 2020/6/18 13:25
 * @description
 */
@RestController
@RequestMapping("activiti")
public class ActivitiController {

    @Autowired
    private ActivitiService activitiService;

    @GetMapping("deploy")
    public ResultBean deploy(String resouceName) {
        this.activitiService.deploy(resouceName);
        return ResultBean.ok("部署成功");
    }

    @GetMapping("start")
    public ResultBean start(String key) {
        this.activitiService.start(key);
        return ResultBean.ok("发起成功");
    }

    @GetMapping("list")
    public ResultBean list() {
        return ResultBean.ok(this.activitiService.processList());
    }

    @GetMapping("task-list")
    public ResultBean taskList(String key) {
        return ResultBean.ok(this.activitiService.taskList(key));
    }

    @GetMapping("task-complete")
    public ResultBean taskComplete(String taskId, String result, String suggestion) {
        this.activitiService.complete(taskId, result, suggestion);
        return ResultBean.ok();
    }

    @GetMapping("isProcessEnd")
    public ResultBean isProcessEnd(String pid) {
        boolean processEnd = this.activitiService.isProcessEnd(pid);
        return ResultBean.ok(processEnd);
    }

    @GetMapping("getCurrectActivity")
    public ResultBean getCurrectActivity(String pid) {
        String name = this.activitiService.getCurrectActivity(pid);
        return ResultBean.ok(name);
    }

}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值