关于在IDEA中SpringBoot项目中activiti工作流的使用详解

记录一下工作流的在Springboot中的使用,,顺便写个demo,概念,什么东西的我就不解释了,如有问题欢迎各位大佬指导一下。

1.创建springboot项目后导入依赖

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

添加配置之后再springboot启动类后面加上一行代码否则启动时会报错

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)

添加数据源以及activiti的配置

spring:
 activiti:
  database-schema-update: drop‐create
   //默认为false,activiti在启动的时候会对比数据库中的表中保存的版本,如果不一样会抛出异常
   // true activiti会对数据库中的表进行更新操作,如果表不存在,则自动创建
   // create_drop 在activiti启动的时候创建表,关闭时删除表,必须手动关闭
   // drop-create 在启动的时候先删除表后再创建新的表
  check-process-definitions: false
 datasource:
  driver-class-name: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
  username: root
  password: root

2.初始化activiti表

这里一共有3种方式去创建

第一种

@Test
  public void initTables() {
    //创建数据源
//    DriverManagerDataSource dataSource=new DriverManagerDataSource();
//    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//    dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
//    dataSource.setUsername("root");
//    dataSource.setPassword("root");

    // 创建流程引擎的配置
    ProcessEngineConfiguration configuration = ProcessEngineConfiguration
        .createStandaloneProcessEngineConfiguration();
    configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
    configuration.setJdbcUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC");
    configuration.setJdbcUsername("root");
    configuration.setJdbcPassword("root");
//		configuration.setDataSource(dataSource);
    /**
     * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE 如果数据库里面没有activit的表,也不会创建
     * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP 创建表,使用完之后删除
     * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE 如果数据库里面没有表,就创建
     *
     * dorp-create 代表如果数据库里面有表,那么先删除再创建
     *
     */
    //配置表的初始化的方式
    configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

    //得到流程引擎
    ProcessEngine processEngine=configuration.buildProcessEngine();
    System.out.println(processEngine);
  }

第二种配置activiti.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" 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
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true%26nullCatalogMeansCurrent=true%26characterEncoding=utf8%26useSSL=false%26serverTimezone=UTC"></property>
    <property name="jdbcUsername" value="root"></property>
    <property name="jdbcPassword" value="root"></property>
    <!--
    flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。
    true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。
    create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。
    drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。 -->
    <property name="databaseSchemaUpdate" value="drop-create"></property>
  </bean>
</beans>

然后写一个测试类

@Test
	public void intiTables2() {
		ProcessEngineConfiguration configuration = ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
		// 得到流程引擎
		ProcessEngine processEngine = configuration.buildProcessEngine();
		System.out.println(processEngine);

	}

第三种方法

  @Test
  public void intiTables3() {
    //必须创建activiti.cfg.xml 并配置好数据库的信息
    ProcessEngine processEngine= ProcessEngines.getDefaultProcessEngine();
    System.out.println(processEngine);
  }

3.打开数据库查看

我们打开数据库查看数据库,会发现activiti已自动帮我们创建了28张表(有的好像也只有24张表,有兴趣的可以研究一下)

这里为大家解释一下各张表的含义:Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。

ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。

ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。

ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。

ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。

ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

#RepositoryService
Select * from act_ge_bytearray; 二进制文件夹表
Select * from act_re_deployment; 流程部署表
Select * from act_re_procdef; 流程定义表
Select * from act_ge_property; 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录

#RuntimeService TaskService  运行时数据库表
Select * from act_ru_excution; 流程启动一次只要没有执行完就会有一条数据
Select * from act_ru_task; 可能有多条数据
Select * from act_ru_variable; 记录流程运行时的流程变量
Select * from act_ru_identitylink; 存放流程办理人的信息

#HistoryService 历史数据库表
Select * from act_hi_procinst; 历史流程实例
Select * from act_hi_taskinst; 历史任务实例
Select * from act_hi_actinst; 历史节点表
Select * from act_hi_attachment; 历史附件表
Select * from act_hicomment; 历史意见表
Select * from act_hi_identitylink; 历史流程人员表
Select * from act_hi_detail; 历史详情表提供历史变量查询
Select * from act_hi_procinst; 历史流程实例表
Select * from act_hi_taskinst; 历史任务实例表
Select * from act_hi_varinst; 历史变量表

#IdentityService 这四张表尽量使用自己的一套,难以满足需求
Select * from act_id_group; 用户组信息表
Select * from act_id_info; 用户拓展信息表
Select * from act_id_menbership; 用户与用户组对应表
Select * from act_id_user; 用户信息表

4.接下来开始画请假流程图(需要先安装插件),新建一个bpm文件开始编辑

Assignee相当于办理人的意思 我这里是zhang 提出申请,主管yuan 审核。

5.部署流程流程

  // 得到流程引擎
	private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

  @Test
  public void deployProcess01() {
    // 得到流程部署的service
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    Deployment deploy = repositoryService.createDeployment().name("请假流程").addClasspathResource("activitiTest.bpmn").deploy();
    System.out.println("部署成功:流程部署ID:" + deploy.getId());
  }

6.启动流程(这里的key与第五部第一张途中对应)

  /**
   * 启动流程
   */
  @Test
  public void startProcess() {
    RuntimeService runtimeService = this.processEngine.getRuntimeService();
//    String processDefinitionId="HelloWorld:1:4";
//		runtimeService.startProcessInstanceById(processDefinitionId);
    String processDefinitionKey="mytest";
    runtimeService.startProcessInstanceByKey(processDefinitionKey);
    System.out.println("流程启动成功");
  }

7.根据用户查询任务(这里使用流程图中的assignee字段)

 @Test
  public void queryTask() {
    TaskService taskService = this.processEngine.getTaskService();
    String assignee="chen";
    List<Task> list = taskService.createTaskQuery().taskAssignee(assignee).list();
    if(null!=list&&list.size()>0) {
      for (Task task : list) {
        System.out.println("任务ID:"+task.getId());
        System.out.println("流程实例ID:"+task.getProcessInstanceId());
        System.out.println("执行实例ID:"+task.getExecutionId());
        System.out.println("流程定义ID:"+task.getProcessDefinitionId());
        System.out.println("任务名称:"+task.getName());
        System.out.println("任务办理人:"+task.getAssignee());
        System.out.println("################################");
      }
    }
  }

8.办理任务(配合步骤8查询出taskid然后进行办理任务)

  @Test
  public void completeTask() {
    TaskService taskService = this.processEngine.getTaskService();
    String taskId="5005";//步骤8中查询出来的taskId
    taskService.complete(taskId);
    System.out.println("任务完成");
  }

重复7、8两个步骤,自此一个完整的请假流程就完成了。

那么肯定会有人问了,如果我想查看一我们流程定义的信息,流程图,删除流程定义等怎么办呢,话不多说直接上代码

package com.example;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.junit.jupiter.api.Test;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

public class TestProcessProdef {
  // 得到流程引擎
  private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

  /**
   * 部署流程使用classpath
   */
  @Test
  public void deployProcess01() {
    // 得到流程部署的service
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    Deployment deploy = repositoryService.createDeployment().name("请假流程2").addClasspathResource("activiti.bpmn").deploy();
    System.out.println("部署成功:流程部署ID:" + deploy.getId());
  }

  /**
   * 查询流程部署信息 act_re_deployment
   */
  @Test
  public void queryProcessDeploy() {
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    // 创建部署信息的查询
    String deploymentId = "1";
//		Deployment deploy = repositoryService.createDeploymentQuery()
    List<Deployment> list = repositoryService.createDeploymentQuery()
        // 条件
        // .deploymentId(deploymentId) //根据部署ID去查询
        // .deploymentName(name)//根据部署名称去查询
        // .deploymentTenantId(tenantId)//根据tenantId去查询
//		.deploymentNameLike(nameLike)//根据部署名称模糊查询
        // .deploymentTenantIdLike(tenantIdLike)//根据tenantId模糊查询
        // 排序
//		.orderByDeploymentId().asc() //根据部署ID升序
        // .orderByDeploymenTime().desc() //根据部署时间降序
        // .orderByDeploymentName()//根据部署名称升序
        // 结果集
        .list(); // 查询返回list集合
//		.listPage(firstResult, maxResults) 分页查询返回list集合
    // .singleResult(); //返回单个对象
//		.count();

    /*
     * System.out.println("部署ID:"+deploy.getId());
     * System.out.println("部署名称:"+deploy.getName());
     * System.out.println("部署时间:"+deploy.getDeploymentTime());
     */
//		System.out.println(count);
    for (Deployment deployment : list) {
      System.out.println("部署ID:" + deployment.getId());
      System.out.println("部署名称:" + deployment.getName());
      System.out.println("部署时间:" + deployment.getDeploymentTime());
      System.out.println("########################");
    }
  }

  /**
   * 查询流程定义
   */
  @Test
  public void queryProcDef() {
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
        // 条件
//		.deploymentId(deploymentId) 根据部署ID查询
//		.deploymentIds(deploymentIds) 根据部署ID的集合查询Set<String> deploymentIds
//		.processDefinitionId(processDefinitionId)//根据流程定义IDHelloWorld:1:4
//		.processDefinitionIds(processDefinitionIds)//根据流程定义的IDS查询
//		.processDefinitionKey(processDefinitionKey)//根据流程定义的的key查询
//		.processDefinitionKeyLike(processDefinitionKeyLike)//根据流程定义的的key模糊查询
//		.processDefinitionName(processDefinitionName)//根据流程定义的名称查询
//		.processDefinitionNameLike(processDefinitionNameLike)//根据流程定义的名称模糊查询
//		.processDefinitionResourceName(resourceName)//根据流程图的BPMN文件名查询
//		.processDefinitionResourceNameLike(resourceNameLike)//根据流程图的BPMN文件名模糊查询
//		.processDefinitionVersion(processDefinitionVersion)//根据流程定义的版本查询
//		.processDefinitionVersionGreaterThan(processDefinitionVersion)//version>num
//		.processDefinitionVersionGreaterThanOrEquals(processDefinitionVersion)//version>=num
//		.processDefinitionVersionLowerThan(processDefinitionVersion)//version<num
//		.processDefinitionVersionLowerThanOrEquals(processDefinitionVersion)//version<=num
        // 排序
//		.orderByDeploymentId()
//		.orderByProcessDefinitionId()
//		.orderByProcessDefinitionKey()
//		.orderByProcessDefinitionName()
//		.orderByProcessDefinitionVersion()
        // 结果集
        .list();
//		.listPage(firstResult, maxResults)\
//		.count()
//		.singleResult()
    if (null != list && list.size() > 0) {
      for (ProcessDefinition pd : list) {
        System.out.println("流程定义ID:" + pd.getId());
        System.out.println("流程部署ID:" + pd.getDeploymentId());
        System.out.println("流程定义KEY:" + pd.getKey());
        System.out.println("流程定义的名称:" + pd.getName());
        System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name
        System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name
        System.out.println("流程定义的版本号:" + pd.getVersion());
        System.out.println("##################");
      }
    }
  }

  /**
   * 启动流程
   */
  @Test
  public void startProcess() {
    RuntimeService runtimeService = this.processEngine.getRuntimeService();
    String processDefinitionKey = "mytest";
    runtimeService.startProcessInstanceByKey(processDefinitionKey);
    System.out.println("流程启动成功");
  }

  /**
   * 删除流程定义
   */
  @Test
  public void deleteProcessDef() {
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    String deploymentId = "2501";
    // 根据流程部署id删除流程定义 如果当前id的流程正在执行,那么会报错
    // repositoryService.deleteDeployment(deploymentId);
    // 根据流程部署id删除删除流程定义 如果当前id的流程正在执行,会把正在执行的流程数据删除 act_ru_*和act_hi_*表里面的数据
    repositoryService.deleteDeployment(deploymentId, true);
//		repositoryService.deleteDeploymentCascade(deploymentId);==repositoryService.deleteDeployment(deploymentId, true);
    System.out.println("删除成功");
  }

  /**
   * 查询流程图 根据流程定义ID
   */
  @Test
  public void viewProcessImg() {
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    String processDefinitionId = "mytest:2:2504";
    InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);

    File file = new File("d:/mytest.png");
    try {
      BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
      int len = 0;
      byte[] b = new byte[1024];
      while ((len = inputStream.read(b)) != -1) {
        outputStream.write(b, 0, len);
        outputStream.flush();
      }
      outputStream.close();
      inputStream.close();
      System.out.println("查询成功");
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  /**
   * 查询流程图 根据流流程部署ID
   */
  @Test
  public void viewProcessImg2() {
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    // 根据流程部署ID查询流程定义对象
    String deploymentId = "1";
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .deploymentId(deploymentId).singleResult();
    // 从流程定义对象里面查询出流程定义ID
    String processDefinitionId = processDefinition.getId();
    InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);

    File file = new File("d:/" + processDefinition.getDiagramResourceName());
    try {
      BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
      int len = 0;
      byte[] b = new byte[1024];
      while ((len = inputStream.read(b)) != -1) {
        outputStream.write(b, 0, len);
        outputStream.flush();
      }
      outputStream.close();
      inputStream.close();
      System.out.println("查询成功");
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  /**
   * 查询最新的流程定义
   */
  @Test
  public void queryNewProcessDef() {
    Map<String, ProcessDefinition> map = new HashMap<>();

    // 查询所有的流程定义根据版本号升序
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
        .orderByProcessDefinitionVersion().asc().list();
    if (null != list && list.size() > 0) {
      for (ProcessDefinition pd : list) {
        map.put(pd.getKey(), pd);
      }
    }
    // 循环map集合
    Collection<ProcessDefinition> values = map.values();
    for (ProcessDefinition pd : values) {
      System.out.println("流程定义ID:" + pd.getId());
      System.out.println("流程部署ID:" + pd.getDeploymentId());
      System.out.println("流程定义KEY:" + pd.getKey());
      System.out.println("流程定义的名称:" + pd.getName());
      System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name
      System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name
      System.out.println("流程定义的版本号:" + pd.getVersion());
      System.out.println("##################");
    }
  }

  /**
   * 已知key 附加功能:删除流程定义(删除key相同的所有不同版本的流程定义)
   */
  public void deleteAllSameVersion() {
    String processDefinitionKey = "mytest";
    RepositoryService repositoryService = this.processEngine.getRepositoryService();
    // 根据流程定义的key查询流程集合
    List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey(processDefinitionKey).list();

    if (null != list && list.size() > 0) {
      for (ProcessDefinition pd : list) {
        repositoryService.deleteDeployment(pd.getDeploymentId(), true);

      }
    }

  }
}

肯定还有人会问,上面的请假流程是走完了,但是没有写请假理由,请假天数,如果是报销单的话 还需要上传报销单据等,那么这个怎么解决呢?这个时候就需要activiti提供给我们的流程变量了,那么什么是流程变量呢?

流程变量在整个工作流中扮演很重要的作用。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是只对应一个流程实例。也就是说各个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。图中红框的信息就是流程变量。

那么我们怎么设置流程变量呢,我们启动流程的时候就可以设置流程变量了,见代码:

	/**
	 * 启动流程
	 */
	@Test
	public void startProcess() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String processDefinitionKey = "mytest";
//		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
		//创建流程变量对象
		Map<String,Object> variables=new HashMap<>();
		variables.put("请假天数", 30);//int
		variables.put("请假原因", "结婚");
		variables.put("请假时间", new Date());
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
		System.out.println("流程启动成功:" + processInstance.getId() + "  " + processInstance.getProcessDefinitionId() + " "
				+ processInstance.getProcessInstanceId());

	}

说明:

1)流程变量的作用域就是流程实例,所以只要设置就行了,不用管在哪个阶段设置

2)基本类型设置流程变量,在taskService中使用任务ID,定义流程变量的名称,设置流程变量的值。

3)Javabean类型设置获取流程变量,除了需要这个javabean实现了Serializable接口外,还要求流程变量对象的属性不能发生变化,否则抛出异常。解决方案,固定序列化ID

4)设置流程变量的时候,向act_ru_variable这个表添加数据

RuntimeService对象可以设置流程变量和获取流程变量  TaskService对象可以设置流程变量和获取流程变量

Map集合的key表示流程变量的名称    Map集合的value表示流程变量的值

查询流程变量以及查询历史流程变量:

	/**
	 * 获取流程变量
	 */
	@Test
	public void getVariables() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String executionId="2501";
		Integer days=(Integer) runtimeService.getVariable(executionId, "请假天数");
		Date date=(Date) runtimeService.getVariable(executionId, "请假时间");
		User user=(User) runtimeService.getVariable(executionId, "用户对象");
		System.out.println(days);
		System.out.println(date.toLocaleString());
		System.out.println(user.getId()+" "+user.getName());
	}

	/**
	 * 7:查询历史的流程变量
	 */
	@Test
	public void getHistoryVariables() {
		HistoryService historyService = this.processEngine.getHistoryService();

		/*HistoricVariableInstance singleResult = historyService.createHistoricVariableInstanceQuery().id("2503").singleResult();;
		System.out.println(singleResult.getId());
		System.out.println(singleResult.getValue());
		System.out.println(singleResult.getVariableName());
		System.out.println(singleResult.getVariableTypeName());*/
		String processInstanceId="2501";
		List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();

		for (HistoricVariableInstance hvs : list) {
			System.out.println("ID"+hvs.getId());
			System.out.println("变量值"+hvs.getValue());
			System.out.println("变量名"+hvs.getVariableName());
			System.out.println("变量类型"+hvs.getVariableTypeName());
			System.out.println("#####################");
		}
	}

查询历史流程实例 、查询历史活动 以及查询历史任务

public class TestHistoryQuery {

	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	HistoryService historyService = this.processEngine.getHistoryService();

	/* 1,查询历史流程实例 */
	@Test
	public void historyProcessInstince() {
		List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
		//条件
//		.processDefinitionId(processDefinitionId)
//		.processDefinitionKey(processDefinitionKey)
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionVersion(processDefinitionVersion)
//		.processInstanceBusinessKey(processInstanceBusinessKey)
//		.processInstanceId(processInstanceId)
//		.processInstanceIds(processInstanceIds)
		//排序
//		.orderByProcessDefinitionId()
//		.orderByProcessInstanceBusinessKey()
//		.orderByProcessInstanceDuration()
//		.orderByProcessInstanceStartTime()
//		.orderByProcessInstanceId()
		//结果集
		.list();
//		.listPage(firstResult, maxResults)
//		.count()
//		.singleResult();

		if(null!=list&&list.size()>0) {
			for (HistoricProcessInstance hpi : list) {
				System.out.println("历史流程实例ID:" + hpi.getId());
				System.out.println("流程定义ID:" + hpi.getProcessDefinitionId());
				System.out.println("历史流程实例的业务ID:" + hpi.getBusinessKey());
				System.out.println("流程部署ID:" + hpi.getDeploymentId());
				System.out.println("流程定义KEY:" + hpi.getProcessDefinitionKey());
				System.out.println("开始活动ID:" + hpi.getStartActivityId());
				System.out.println("结束活动ID:" + hpi.getEndActivityId());
				System.out.println("########################");
			}
		}

	}

	/* 2,查询历史活动 */
	@Test
	public void queryHistoryAct() {
		List<HistoricActivityInstance> list = this.historyService.createHistoricActivityInstanceQuery()
		//条件
//		.activityId(activityId)
//		.activityInstanceId(activityInstanceId)
//		.activityName(activityName)
		//排序
//		.orderByActivityId()
//		.orderByActivityName()
		//结果集
		.list();
		if(null!=list&&list.size()>0)
		{
			for (HistoricActivityInstance hai : list) {
				System.out.println("ID:"+hai.getId());
				System.out.println("流程定义ID:"+hai.getProcessDefinitionId());
				System.out.println("流程实例ID:"+hai.getProcessInstanceId());
				System.out.println("执行实例ID:"+hai.getExecutionId());
				System.out.println("活动ID:"+hai.getActivityId());
				System.out.println("任务ID:"+hai.getTaskId());
				System.out.println("活动名称:"+hai.getActivityName());
				System.out.println("活动类型:"+hai.getActivityType());
				System.out.println("任务办理人:"+hai.getAssignee());
				System.out.println("开始时间:"+hai.getStartTime());
				System.out.println("结束时间:"+hai.getEndTime());
				System.out.println("持续时间:"+hai.getDurationInMillis());
				System.out.println("#######################################");
			}
		}
	}
	/* 3,查询历史任务 act_hi_taskinst */
	@Test
	public void queryHistoryTask() {
		List<HistoricTaskInstance> list = this.historyService.createHistoricTaskInstanceQuery()
		//条件
//		.deploymentId(deploymentId)
//		.deploymentIdIn(deploymentIds)
//		.executionId(executionId)
//		.processDefinitionId(processDefinitionId)
//		.processDefinitionKey(processDefinitionKey)
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionKeyLike(processDefinitionKeyLike)   processDefinitionKeyLike="%Hello%"
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionNameLike(processDefinitionNameLike)
		//排序
//		.orderByTaskDefinitionKey()
		//结果集
		.list();
//		.listPage(firstResult, maxResults)
//		.count()
//		.singleResult()
		if(null!=list&&list.size()>0)
		{
			for (HistoricTaskInstance task : list) {
				System.out.println("任务ID:" + task.getId());
				System.out.println("任务办理人:" + task.getAssignee());
				System.out.println("执行实例ID:" + task.getExecutionId());
				System.out.println("任务名称:" + task.getName());
				System.out.println("流程定义ID:" + task.getProcessDefinitionId());
				System.out.println("流程实例ID:" + task.getProcessInstanceId());
				System.out.println("任务创建时间:" + task.getCreateTime());
				System.out.println("任务结束时间:" + task.getEndTime());
				System.out.println("#######################################");
			}
		}
	}
}

最近我发现上面的代码不能完全在开发中应用,比如上面的用户申请是在画流程图的时候写死的,在实际开发中肯定是根据当前登录的用户来提出申请,另外还没有分支的情况,所以我特地修改了一下流程图。

这个流程图中 没有设置用户,在Condition中传入参数#{UserId},后面的重要与不重要分支同样加上Condition条件${message=='重要'}和${message=='不重要'},然后主管审核和总经理的assignee可以设置成固定的值也可以像用户一样根据传参设置。接下来直接上代码

1.启动流程

 /**启动流程实例*/

  @Test
  public void startProcessInstance(){
    String processDefinitionKey = "myProcess_1";
    /**启动流程实例的同时,设置流程变量,使用流程变量用来指定任务的办理人,对应task.pbmn文件中#{userID}*/

    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("userID", "袁志豪");
    ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
     .startProcessInstanceByKey(processDefinitionKey,variables);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动

    System.out.println("流程实例ID:"+pi.getId());//流程实例ID  101

    System.out.println("流程定义ID:"+pi.getProcessDefinitionId());//流程定义ID

  }

用户完成申请提交,主管在流成图中没有设置固定值

  @Test
  public void completeTask() {
    TaskService taskService = this.processEngine.getTaskService();
    String taskId = "2508";
    // 根据任务ID去完成任务
   // taskService.complete(taskId);
    // 根据任务ID去完成任务并指定流程变量
    Map<String,Object > variable =new HashMap<>();
    String shenheren ="张三";//实际开发中可在前台选择主管传入后台
    variable.put("zhuguan","张三");//这里的 zhuguan 和 activiti.bpmn中的#{zhuguan}保持一致,既可以设置下一级审核主管
		taskService.complete(taskId, variables);
    System.out.println("任务完成");
  }

主管审核

  @Test
  public void complateTask2(){
    TaskService taskService = this.processEngine.getTaskService();
    String taskId2= "5002";
    Map<String,Object > variable =new HashMap<>();
    /***这里的message 是流程图中分支条件message,根据传入的参数判断走那一条线***/
    variable.put("message","重要");
//    variable.put("message","不重要");
    taskService.complete(taskId2,variable);
  }

经理审核

 @Test
  public void complateTask3(){
    TaskService taskService = this.processEngine.getTaskService();
    String taskId2= "7503";
    Map<String,Object > variable =new HashMap<>();
    variable.put("审核意见","好好休假注意身体");//领导审核意见
    taskService.complete(taskId2,variable);
  }

另外我在开发中发现在流程图画完之后将bpmn后缀改为xml方式生成图片之后,再次改为bpmn的时候,发现之前写的Condition中变成了\n,如图

我们再次将后缀改为xml之后查看我们的条件:

解决方式:

将condition前面后面的空格删掉即可;

到此这篇关于关于在IDEA中SpringBoot项目中activiti工作流的使用详解的文章就介绍到这了,更多相关IDEA SpringBoot activiti工作流内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring Boot中使用Activiti的方法教程(二)

    前言 前面一节我们已经了解了Activiti的基础概念,包括流程定义的用语和它的API功能,已经如何入手Activiti,在这一节我们将结合代码具体学习使用.小图是我们需要完成的请假流程图: 正如我们在图中看到的,这是一个非常简单的流程:员工提出休假请求,提供休假天数和开始日期.请求发送给经理.他们可以批准/拒绝该请求. 如果获得批准,则会定义一个服务任务serviceTask来发送确认电子邮件.如果被拒绝,员工可以选择修改并重新发送请求,也可以不执行任何操作. 此流程的BPMN 2.0定义文件

  • SpringBoot2整合activiti6环境搭建过程解析

    这篇文章主要介绍了SpringBoot2整合activiti6环境搭建过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </d

  • spring boot activiti工作流的搭建与简单使用

    前言 最近一直研究springboot,根据工作需求,工作流需要作为一个单独的微服务工程来提供给其他服务调用,现在简单的写下工作流(使用的activiti)微服务的搭建与简单使用 jdk:1.8 数据库:mysql  5.7 IDE:eclipse springboot:1.5.8 activiti:6.0.0 1.新建空白的maven微服务架构 新建maven项目的流程不在阐述,这里添加上activiti.myslq连接的依赖,只贴主要代码 pox.xml <project xmlns="

  • SpringBoot整合Activiti7的实现代码

    Activiti7发布正式版之后,它与SpringBoot2.x已经完全支持整合开发.我们可以将Activiti7与SpringBoot整合开发的坐标引入到工程中,从而达到SpringBoot支持Activti7整合. 1.使用IDEA创建SpringBoot项目 在工程的pom.xml文件中引入相关的依赖,具体依赖如下所示 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="ht

  • Spring Boot中使用activiti的方法教程(一)

    前言 Activiti API是一个工作流程(workflow)和业务流程管理(BPM)系统,可以定义流程.执行流程并以不同方式对其实现运行.使用API​​的开发可以在任何IDE中完成,但是要使用Activiti Designer需要Eclipse,IDEA中使用actiBPM插件. 定义流程有几种方式: 1. 使用BPMN 2.0标准在定义一个流程XML. 2. 使用StartEvent,EndEvent,UserTask,SequenceFlow等Java类. 如果我们想要运行进程或访问任何

  • 解决Springboot2.1.x配置Activiti7单独数据源问题

    1|1简介 最近基于最新的Activiti7配置了SpringBoot2. 简单上手使用了一番.发现市面上解决Activiti7的教程很少,采坑也比较多,在Activiti6配置数据源和Activiti7有所区别,基于Activiti6在Activiti7里是无法正常使用的.接下来让我们看下区别. 1|2问题 Activiti6多数据源配置 6的配置比较简单点. 先加入配置: # activiti 数据源 spring.datasource.activiti.driver=com.mysql.j

  • 关于在IDEA中SpringBoot项目中activiti工作流的使用详解

    记录一下工作流的在Springboot中的使用,,顺便写个demo,概念,什么东西的我就不解释了,如有问题欢迎各位大佬指导一下. 1.创建springboot项目后导入依赖 <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version&

  • IDEA SpringBoot项目配置热更新的步骤详解(无需每次手动重启服务器)

    IDEA SpringBoot项目配置热更新的步骤 1.在pom.xml中添加依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> 2.在pom.xml中添加插件: <

  • SpringBoot项目如何打war包问题详解

    1.pom.xml配置修改 <packaging>jar</packaging> //修改为 <packaging>war</packaging> 2.pom文件添加如些依赖 <!--添加servlet-api的依赖,用来打war包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</

  • SpringBoot项目使用mybatis-plus代码生成的实例详解

    目录 前言 安装依赖 application.yml添加配置 代码生成实例 代码生成依赖 数据源配置 globalConfig处理通用配置 packageConfig包名设置 strategyConfig配置 小结 总结 前言 mybatis-plus官方地址 https://baomidou.com mybatis-plus是mybatis的增强,不对mybatis做任何改变,涵盖了代码生成,自定义ID生成器,快速实现CRUD,自动分页,逻辑删除等功能,更多功能请查阅官方文档 安装依赖 myb

  • springboot项目idea热部署的教程详解

    1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> <scope>true</scope> </dependency> 2.开启自动编译 3.ctrl+shifi+alt

  • SpringBoot项目中的多数据源支持的方法

    1.概述 项目中经常会遇到一个应用需要访问多个数据源的情况,本文介绍在SpringBoot项目中利用SpringDataJpa技术如何支持多个数据库的数据源. 具体的代码参照该 示例项目 2.建立实体类(Entity) 首先,我们创建两个简单的实体类,分别属于两个不同的数据源,用于演示多数据源数据的保存和查询. Test实体类: package com.example.demo.test.data; import javax.persistence.Entity; import javax.pe

  • SpringBoot项目中使用redis缓存的方法步骤

    本文介绍了SpringBoot项目中使用redis缓存的方法步骤,分享给大家,具体如下: Spring Data Redis为我们封装了Redis客户端的各种操作,简化使用. - 当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作 - 当Redis作为缓存使用时,我们可以将它作为Spring Cache的实现,直接通过注解使用 1.概述 在应用中有效的利用redis缓存可以很好的提升系统性能,特别是对于查询操作,可以有效的减少数据库压力. 具体的代码参照该

  • SpringBoot项目中使用AOP的方法

    本文介绍了SpringBoot项目中使用AOP的方法,分享给大家,具体如下: 1.概述 将通用的逻辑用AOP技术实现可以极大的简化程序的编写,例如验签.鉴权等.Spring的声明式事务也是通过AOP技术实现的. 具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-aop Spring的AOP技术主要有4个核心概念: Pointcut: 切点,用于定义哪个方法会被拦截,例如 execution(* cn.sp

  • IntelliJ IDEA中SpringBoot项目通过devtools实现热部署的方法

    简要几个步骤: 一.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> 二.开启热部署 <build> <plugins> <plugin&

  • 在SpringBoot项目中利用maven的generate插件

    使用maven 插件 generate生成MyBatis相关文件 在项目中增加 maven 依赖 - mybatis-spring-boot-starter - mysql-connector-java - mybatis-generator-maven-plugin 插件 自动读取 resources 下的generatorConfig.xml 文件 <?xml version="1.0" encoding="UTF-8"?> <project

随机推荐