activiti入门和流程的运行过程(附代码)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Honnyee/article/details/83374057

1.定义bpmn文件,这个文件里是用来定义流程的

2.发布流程

 发布流程,流程的key值相同的情况下每次发布一次,这个流程在数据库的版本会+1

3.查看流程定义

打印的信息

可以看到,我刚才定义的流程已经更新了,现在是版本2了

4.创建流程实例

这里是使用key来创建一个流程

5.查看任务

创建一个实例之后,开始执行流程。一个流程分为很多的节点,每个节点对于不同的人就是不同的任务,所以要运行流程就是从查看自己的任务开始。

在流程定义时我们可以看到 ,start之后,第一个执行事件是提出申请,assignee设定的是 staff

所以查询任务的时候,可以根据staff查看任务

运行代码后,看到了任务相关信息

在数据库中我们可以看到相关信息

6.办理任务

这里的taskId就是上一步查出来的任务id,将任务Id传进taskService.complete的参数中,运行

运行完成后,数据库表中的信息也更新

因为此时流程实例已经走到下一步,此时这个实例的名字是请假审批而不是提出申请了。

然后执行taskId为25002的任务,走到最后一步任务,这个流程实例就完成了。

一定要注意在操作过程中,数据库的变化,这样才能更好更快的理解activiti框架

附代码:

pom.xml引入依赖

    <!--- Activiti依赖导入 -->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>5.18.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.activiti</groupId>
          <artifactId>activiti-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>


    <!--- Activiti依赖导入 -->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>5.18.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.activiti</groupId>
          <artifactId>activiti-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-engine</artifactId>
      <version>5.18.0</version>
      <exclusions>
        <exclusion>
          <artifactId>slf4j-api</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>jcl-over-slf4j</artifactId>
        </exclusion>
        <exclusion>
          <artifactId>spring-beans</artifactId>
          <groupId>org.springframework</groupId>
        </exclusion>
        <exclusion>
          <artifactId>jackson-core-asl</artifactId>
          <groupId>org.codehaus.jackson</groupId>
        </exclusion>
        <exclusion>
          <artifactId>commons-lang3</artifactId>
          <groupId>org.apache.commons</groupId>
        </exclusion>
        <exclusion>
          <artifactId>mybatis</artifactId>
          <groupId>org.mybatis</groupId>
        </exclusion>

      </exclusions>

    </dependency>

注意这里的<esclusion> 排除里面相关的依赖

测试类的代码:


public class activitiTest {

    /**
     *  一条语句创建processEngine, 要求:
     * 1、配置文件必须在classpath根目录下
     * 2、配置文件名必须为activiti-context.xml或activiti.cfg.xml
     * 3、工厂对象的id必须为processEngine
     */
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    HistoryService historyService = processEngine.getHistoryService();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    TaskService taskService = processEngine.getTaskService();

     /** 通过zipinputstream完成部署
     * 注意:这个的话,需要将bpmn和png文件进行压缩成zip文件,然后放在项目src目录下即可(当然其他目录也可以)
     */
    @Test
    public void testDeployFromZipinputStream(){
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("shenqing.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
                .createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
    }

    /**
     * 创建ActivitiEngine 生成数据库表
     */
    @Test
    public void createActivitiEngine(){

        //取得ProcessEngineConfiguration对象
        ProcessEngineConfiguration engineConfiguration=ProcessEngineConfiguration.
                createStandaloneProcessEngineConfiguration();

        /**2. 通过加载 activiti.cfg.xml 获取 流程引擎 和自动创建数据库及表*/

        // 设置创建表的策略 (当没有表时,自动创建表)
        // = "false";//不会自动创建表,没有表,则抛异常
        // = "create-drop";//先删除,再创建表
        // = "true";//假如没有表,则自动创建
        engineConfiguration.setDatabaseSchemaUpdate("true");
        //通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
        ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
        System.out.println("流程引擎创建成功!");

    }


    /**
     * 查看流程图
     * 根据deploymentId和name(在act_ge_bytearray数据表中)
     */
    @Test
    public void testShowImage() throws Exception{
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        InputStream inputStream = processEngine.getRepositoryService()
                /**
                 * deploymentID
                 * 文件的名称和路径
                 */
                .getResourceAsStream("110003","activiti/weekReport.bpmn");
        OutputStream outputStream3 = new FileOutputStream("e:/weekReport.png");
        int b = -1 ;
        while ((b=inputStream.read())!=-1){
            outputStream3.write(b);
        }
        inputStream.close();
        outputStream3.close();
    }

    /**
     * 根据pdid查看图片(在act_re_procdef数据表中)
     * @throws Exception
     */
    @Test
    public void testShowImage2() throws Exception{
        InputStream inputStream = processEngine.getRepositoryService()
                .getProcessDiagram("leaveProcess:13:120004");
        OutputStream outputStream = new FileOutputStream("e:/leaveProcess.png");
        int b = -1 ;
        while ((b=inputStream.read())!=-1){
            outputStream.write(b);
        }
        inputStream.close();
        outputStream.close();
    }

    /**
     * 部署流程定义
     */
    @Test
    public void deploy() {

        //获取仓库服务 :管理流程定义
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
                .addClasspathResource("activiti/weekReport.bpmn")//从类路径中添加资源,一次只能添加一个资源
                .name("周报审批流程")//设置部署的名称
                .category("直销部")//设置部署的类别
                .deploy();

        System.out.println("部署的id"+deploy.getId());
        System.out.println("部署的名称"+deploy.getName());
    }

    /**
     * 创建流程实例
     */
    @Test
    public void startProcessInstance(){
        String leaveId = "007";
        String staffId = "04643";
        HashMap<String,Object> map=new HashMap<>();
        map.put("staffId",staffId);
        // 启动流程
        String processInstanceKey = "weekReportProcess";
//        三个参数分别为(String processDefinitionKey, String businessKey, HashMap<String, Object> variables)
        ProcessInstance pi = processEngine.getRuntimeService()
                .startProcessInstanceByKey(processInstanceKey,leaveId,map);
        System.out.println("创建流程实例成功,流程实例id:"+pi.getId()
                + "  流程定义id:" + pi.getProcessDefinitionId());
        //默认完成第一步申请人的申请步骤
        Task task = processEngine.getTaskService()
                .createTaskQuery()
                .processInstanceId(pi.getId())
                .singleResult();
        String nextStaffId = "04646";
        map.put("staffId",nextStaffId);
        processEngine.getTaskService()
                .complete(task.getId(),map);
    }

    /**
     * 查询所有的正在执行的任务
     */
    @Test
    public void testQueryTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Task> tasks = processEngine.getTaskService()
                .createTaskQuery()
                .list();
        for (Task task : tasks) {
            System.out.println(task.getName());
        }
    }

    /**
     * 根据piid得到当前正在执行的流程实例的正在活动的节点
     */
    @Test
    public void testActivity(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        /**
         * 根据piid得到流程实例
         */
        ProcessInstance pi = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processInstanceId("127501")
                .singleResult();
        String activityId = pi.getActivityId();//当前流程实例正在执行的activityId
        System.out.println(activityId);
    }

    /**
     * 查找个人任务
     */
    @Test
    public void getMyTaskInfo() {
        String staffId = "007";
        List<Task> listTask = processEngine.getTaskService()
                .createTaskQuery()
                .taskAssignee(staffId)
                .list();

        if (listTask != null && listTask.size() > 0) {
            for (Task task : listTask) {
                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.getProcessDefinitionId());
                System.out.println("#########################################");
            }
        }
    }

    /**
     *  执行任务
     * @return
     */
    @Test
    public void completeMyPersonTask() {
        String taskId = "170002";
        String nextStaffId = "02222";
        HashMap<String,Object> map=new HashMap<>();
        map.put("staffId",nextStaffId);
        processEngine.getTaskService()
                .complete(taskId,map);
        System.out.println("查看当前任务成功"+"完成任务,任务ID:" + taskId);
    }

    /**
     *  终止流程实例
     * @return
     */
    @Test
    public void deleteProcessInstance() {
        String taskId = "135002";
        String reason = "太少了,100个新增!";
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId()).singleResult();
        processEngine.getRuntimeService()
                .deleteProcessInstance(processInstance.getId(),reason);
        System.out.println("停止taskId为:" + taskId+"的任务");
    }

    /**
     * 查询执行对象表,使用流程实例ID和当前活动的名称(receivetask1)
     */
    @Test
    public void queryExecution(){
        ProcessInstance pi = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processDefinitionKey("weekReportProcess")
                .singleResult();
        //3.查询执行对象表,使用流程实例ID和当前活动的名称(receivetask1)
        String processInstanceId = pi.getId();//得到流程实例ID
        Execution execution1 = processEngine.getRuntimeService()
                .createExecutionQuery()
                .processInstanceId(processInstanceId)//流程实例ID
//                .activityId("receivetask1")//当前活动的名称
                .singleResult();
        //5.向后执行一步
        processEngine.getRuntimeService()
                .signal(execution1.getId());

    }

    /**
     *  直接跳过某一个执行步骤
     * @return
     */
    @Test
    public void passTask() {
        String executionId =  "127501";
        processEngine.getRuntimeService().signal(executionId);
        System.out.println("直接执行下一步");
    }

    /**
     * 直接完成执行者为空的步骤,直到有执行者的那一步并设置执行者id
     */
    @Test
    public void passNull(){
        TaskService taskService = processEngine.getTaskService();
        //上一个任务的执行者
        String assignee =  "04646";
        //当前流程实例Id
        String processInstanceId = "165001";

        //整个流程中,所有节点涉及的执行人全部加入到一个数组中
        ArrayList<String>  assignees= new ArrayList<>();
        assignees.add("04643");
        assignees.add("04646");
        assignees.add("");
        assignees.add("007");

        //获得上一个执行者后面的数组
        List<String> subAssigneeList = assignees.subList(assignees.indexOf(assignee)+1, assignees.size());
        //遍历数组 查找下一个执行者是否为空
        //如果为空就默认完成进入下一步,直到第一个不为空的执行者 跳出foreach
        for (String l:subAssigneeList
             ) {
            System.out.println("subList的位置"+subAssigneeList.indexOf(l)+"元素是:"+l);

            //如果 下一个任务的执行人为空,直接默认完成这一步,并根据数组将下一个执行人加入下一个任务中
            if (l.equals(null) || l.length() == 0){
                Task task = taskService.createTaskQuery()
                        .processInstanceId(processInstanceId)
                        .singleResult();
                HashMap<String, Object> var = new HashMap<>();
                var.put("staffId",subAssigneeList.get( subAssigneeList.indexOf(l) + 1));
                taskService.complete(task.getId(),var);
                System.out.println("这个位置的执行者是空,直接默认完成这一步");
            }else {
                System.out.println("存在执行者,跳出此循环");
                break;
            }
        }
        System.out.println(subAssigneeList);
    }

    @Test
    public void queryProcessInstanceHistory(){
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .orderByHistoricActivityInstanceEndTime()
                .desc()
                .processInstanceId("132501")
                .list();
        for (HistoricActivityInstance h:list){
            System.out.println(h.getId());
            System.out.println(h.getActivityId());
            System.out.println(h.getAssignee());
            System.out.println(h.getExecutionId());
            System.out.println(h.getProcessInstanceId());
            System.out.println("##############################");

        }
    }

}

activiti.cfg.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:sqlserver://xxxDatabaseName=activititest" />
        <property name="jdbcDriver" value="" />
        <property name="jdbcUsername" value="" />
        <property name="jdbcPassword" value="" />
        <!-- 建表策略 -->
        <!--
            "false";不能自动创建表,需要表存在
            "create-drop";先删除表再创建表
            "true";如果表不存在,自动创建表
            -->
        <property name="databaseSchemaUpdate" value="true" />
    </bean>

</beans>

spring配置文件里可以这么配置

 <!-- 配置activiti -->
        <context:component-scan base-package="com.wolwo.activiti">
                <context:exclude-filter type="annotation"
                                        expression="org.springframework.stereotype.Controller" />
                <context:exclude-filter type="annotation"
                                        expression="org.springframework.web.bind.annotation.ControllerAdvice" />
        </context:component-scan>


        <!-- 配置流程引擎文件 -->
        <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
                <property name="dataSource" ref="dataSource" />
                <property name="transactionManager" ref="transactionManager" />
                <property name="labelFontName" value="宋体"/>
                <property name="activityFontName" value="宋体" />
                <!-- 是否自动创建23张表 -->
                <property name="databaseSchemaUpdate" value="true" />

                <property name="jobExecutorActivate" value="false" />
                <property name="deploymentResources" value="activiti/**/*.bpmn"/>
        </bean>

        <!-- 配置创建流程引擎对象 -->
        <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
        </bean>

        <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
        <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
        <bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
        <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
        <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
        <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
        <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />

猜你喜欢

转载自blog.csdn.net/Honnyee/article/details/83374057