Aciviti工作流

1. springBoot和activiti整合

  • pom.xml文件
<?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.7.14</version><relativePath/></parent><groupId>com.activiti7</groupId><artifactId>activiti7</artifactId><version>0.0.1-SNAPSHOT</version><name>activiti7</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</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Mysql驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency><!-- activiti --><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId><version>7.1.0.M6</version></dependency><!-- 注意:activiti需要引入springSecurity包 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • 数据库的Config文件
@Configuration
public class DruidConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driver-class-name}")private String driverClassName;@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setDriverClassName(driverClassName);// 其他 Druid 相关配置,如最大连接数、初始连接数等return dataSource;}@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource());}
}
  • activiti的config配置类
@Configuration
public class ActivitiConfiguration {@Autowiredprivate DataSource dataSource;@Autowiredprivate PlatformTransactionManager platformTransactionManager;public ActivitiConfiguration() {}//通过@Bean注解将SpringProcessEngineConfiguration实例声明为Spring Bean,使其可供其他组件注入和使用@Beanpublic SpringProcessEngineConfiguration springProcessEngineConfiguration() {SpringProcessEngineConfiguration spec = new SpringProcessEngineConfiguration();//设置数据源,将注入的数据源设置到SpringProcessEngineConfiguration实例中spec.setDataSource(this.dataSource);//设置事务管理器将注入的事务管理器设置到SpringProcessEngineConfiguration实例中spec.setTransactionManager(this.platformTransactionManager);//设置数据库模式更新策略 true表示在启动时自动创建或更新Activiti引擎所需的数据库表结构spec.setDatabaseSchemaUpdate("true");//				这里我在部署项目的时候自己加载了bpmn文件,所以把这的扫面关掉了。
//                Resource[] resources = null;
//                //配置流程部署资源
//                //使用PathMatchingResourcePatternResolver从classpath中的bpmn目录下加载所有以.bpmn为扩展名的文件作为流程定义资源,
//                // 并将它们设置到SpringProcessEngineConfiguration实例中。
//                try {
//                        resources = (new PathMatchingResourcePatternResolver()).getResources("classpath*:bpmn/*.bpmn");
//                } catch (IOException var4) {
//                        var4.printStackTrace();
//                }
//                spec.setDeploymentResources(resources);return spec;}
}
  • yaml文件
spring:datasource:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://123.57.27.43:3306/activiti?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=trueusername: rootpassword: newpwd

注意:启动项目前需要提前创建好需要用到的数据库

配置完成后启动项目,启动完成后activiti数据库会自动创建25张activiti相关的表

2. activiti基础

@SpringBootTest
class Activiti7Base {/*部署流程1.只提供了一种类目录加载的方式,还有流、zip等方式。2.act_re_deployment表和act_re_procdef表3.注意:act_re_deployment表有一个系统自带的流程每次启动项目都会升级版本(暂时没研究)*/@Testvoid contextLoads() {// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到repositoryService实例RepositoryService repositoryService = processEngine.getRepositoryService();// 使用repositoryService进行部署Deployment deployment = repositoryService.createDeployment().addClasspathResource("bpmn/diagram6.bpmn").addClasspathResource("bpmn/diagram6.svg").name("请假申请流程-10").deploy();System.out.println("流程部署id:"+deployment.getId());System.out.println("流程部署名称:"+deployment.getName());}/*启动流程*/@Testvoid startProcess(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取runtimeService实例RuntimeService runtimeService = processEngine.getRuntimeService();// 根据流程定义Id启动流程ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("java110_752023081032120386");System.out.println("流程定义Id:"+processInstance.getProcessDefinitionId());System.out.println("流程实例Id:"+processInstance.getId());System.out.println("当前活动Id:"+processInstance.getActivityId());}/*查询用户任务1.act_ru_task表*/@Testvoid queryUserTask(){// 负责人
//                String assignee = "mps1";
//                String assignee = "mps2";// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 创建taskServiceTaskService taskService = processEngine.getTaskService();// 根据流程key 和 任务负责人 查询任务List<Task> list = taskService.createTaskQuery().processDefinitionKey("java110_752023081032120386")
//                        .taskAssignee(assignee).list();for(Task task : list){System.out.println("-------------------------");System.out.println("流程实例id:"+task.getProcessInstanceId());System.out.println("任务id:"+task.getId());System.out.println("任务负责人:"+task.getAssignee());System.out.println("任务名称:"+task.getName());}}/*用户完成任务*/@Testvoid finishTask(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 创建taskServiceTaskService taskService = processEngine.getTaskService();// 根据流程key 和 任务负责人 查询任务Task task = taskService.createTaskQuery().processDefinitionKey("java110_752023081032120386").processInstanceId("2502") //流程实例id.taskAssignee("mps8").singleResult(); //singleResult()只返回一个任务,如果查询结果有零个或多个任务会抛异常// 完成任务, 参数任务idtaskService.complete(task.getId());}/*查询流程定义*/@Testvoid queryProcess(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 获取processDefinitionQuery对象ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();// 查询当前所有的流程定义List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("java110_752023081032120386").orderByProcessDefinitionVersion().desc().list();for(ProcessDefinition processDefinition : definitionList){System.out.println("流程定义 id="+processDefinition.getId());System.out.println("流程定义 name="+processDefinition.getName());System.out.println("流程定义 key="+processDefinition.getKey());System.out.println("流程定义 Version="+processDefinition.getVersion());System.out.println("流程部署ID="+processDefinition.getDeploymentId());}}/*查询当前流程实例*/@Testvoid queryProcessInstance(){// 流程定义keyString processDefinitionKey = "java110_752023081032120386";// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取runtimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey).list();for(ProcessInstance processInstance : list){System.out.println("---------------------------");System.out.println("流程实例id:"+processInstance.getProcessInstanceId());System.out.println("所属流程定义id:"+processInstance.getProcessDefinitionId());System.out.println("是否执行完成:"+processInstance.isEnded());System.out.println("是否暂停:"+processInstance.isSuspended());System.out.println("当前活动标识:"+processInstance.getActivityId());System.out.println("业务关键字:"+processInstance.getBusinessKey());}}/*下载流程bpmn 和 图片*/@Testvoid download() throws IOException {// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 得到processDefinition,设置查询条件,得到想要的流程定义ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("java110_752023081032120386").singleResult();// 通过流程定义信息,得到部署IDString deploymentId = processDefinition.getDeploymentId();// 读取图片和bpmnInputStream pngInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());// 构造流File file_png = new File("D:/idea/work/activiti7/src/main/resources/download/aaa.svg");File file_bpmn = new File("D:/idea/work/activiti7/src/main/resources/download/aaa.bpmn");FileOutputStream bpmnOut = new FileOutputStream(file_bpmn);FileOutputStream pngOut = new FileOutputStream(file_png);// 输出IOUtils.copy(pngInput,pngOut);IOUtils.copy(bpmnInput,bpmnOut);// 关闭流pngOut.close();bpmnOut.close();pngInput.close();bpmnInput.close();}/*查询历史记录1.act_hi_actinst表*/@Testvoid queryHistoryInfo(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取historyServiceHistoryService historyService = processEngine.getHistoryService();// 获取act_hi_actinst表的查询对象HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();// 设置条件instanceQuery.processInstanceId("5002");// 根据开始时间升序instanceQuery.orderByHistoricActivityInstanceStartTime().asc();// 查询所有内容List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();for(HistoricActivityInstance hi : activityInstanceList){System.out.println(hi.getActivityId());System.out.println(hi.getActivityName());System.out.println(hi.getProcessDefinitionId());System.out.println(hi.getProcessInstanceId());System.out.println("<================================>");}}/*流程定义与流程实例1.流程定义ProcessDefinition和流程实例ProcessInstance是Activti中非常重要的两个概念。他们的关系其实类似于JAVA中类和对象的概念。2.流程定义ProcessDefinition是以BPMN文件定义的一个工作流程,是一组工作规范。例如我们之前定义的请假流程。流程实例ProcessInstance则是指一个具体的业务流程。例如某个员工发起-一次请假,就会实例化一一个请假的流程实例,并且每个不同的流程实例之间是互不影响的。3.在后台的表结构中,有很多张表都包含了流程定义ProcessDefinetion和流程实例rocsslnstance的字段。流程定义的字段通常是PROC_DEF_ID,而流程实例的字段通常是PROC_INST_ID。ProcessEngine对象1.processEngine.getRepositoryService() 	//流程定义对象2.processEngine.getRuntimeService() 	//运行时的对象(实例对象)3.processEngine.getHistoryService() 	//历史记录对象4.processEngine.getTaskService() 		//任务对象*/
}

3. activiti进阶

@SpringBootTest
public class Activiti7Progress {/*启动任务时,添加业务key*/@Testvoid addBusinessKey(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取runtimeService实例RuntimeService runtimeService = processEngine.getRuntimeService();// 根据流程定义Id启动流程ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("java110_752023081032120386","1001");System.out.println("businessKey:"+processInstance.getBusinessKey());}/*整个流程的挂起和激活 ,挂起就是让改流程停止服务*/@Testvoid suspendAllProcessInstance(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 得到processDefinition,设置查询条件,得到想要的流程定义ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("java110_752023081032120386").singleResult();// 获取当前流程是否是挂起状态boolean suspended = processDefinition.isSuspended();// 获取流程定义的idString definitionId = processDefinition.getId();// 如果是挂起状态,改为激活状态 否在挂起if(suspended){repositoryService.activateProcessDefinitionById(definitionId,true,null);System.out.println("流程定义id:"+definitionId+",已激活");}else {repositoryService.suspendProcessDefinitionById(definitionId,true,null);System.out.println("流程定义id:"+definitionId+",已挂起");}}/*挂起单个流程实例*/@Testvoid suspendSingleProcessInstance(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 获取runtimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();// 得到runtimeService,设置查询条件,得到想要的流程定义ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId("30002").singleResult();// 获取当前流程是否是挂起状态boolean suspended = instance.isSuspended();// 获取流程定义的idString definitionId = instance.getId();// 如果是挂起状态,改为激活状态 否在挂起if(suspended){runtimeService.activateProcessInstanceById(definitionId);System.out.println("流程定义id:"+definitionId+",已激活");}else {runtimeService.suspendProcessInstanceById(definitionId);System.out.println("流程定义id:"+definitionId+",已挂起");}}/*启动流程,带流程map变量1.涉及到的bpmn文件和网关图片放在下面*/@Testvoid startProcessM(){// 创建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 流程定义的keyString key = "java110_752023081032120386";// 流程变量mapHashMap<String, Object> variables = new HashMap<>();// 设置流程变量Evection evection = new Evection();// 设置请假日期evection.setNum(4d);// 把流程变量放入mapvariables.put("evection",evection);// 设置任务负责人
//                variables.put("assignee0","李四1");
//                variables.put("assignee1","王经理1");
//                variables.put("assignee2","杨总经理1");
//                variables.put("assignee3","张财务1");// 获取runtimeService实例RuntimeService runtimeService = processEngine.getRuntimeService();// 根据流程定义Id启动流程ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,variables);System.out.println("流程定义Id:"+processInstance.getProcessDefinitionId());System.out.println("流程实例Id:"+processInstance.getId());System.out.println("当前活动Id:"+processInstance.getActivityId());}/*查询候选用户*/@Testvoid queryUsers(){//得到ProcessEngine对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//得到TaskService对象TaskService taskService = processEngine.getTaskService();//设置一些参数,流程定义的key,候选用户String key = "java110_752023081032120386";String candidateUsers = "mps8";//4.执行查询List<Task> list = taskService.createTaskQuery().processDefinitionKey(key).taskCandidateUser(candidateUsers)//设置候选用户.list();for (Task task : list) {System.out.println(task.getProcessInstanceId());System.out.println(task.getId());System.out.println(task.getName());System.out.println(task.getAssignee());//为null,说明当前的mps7只是一个候选人,并不是任务的执行人(需要拾取任务)}}/*查询候选用户组*/@Testvoid queryGroup(){// 得到ProcessEngine对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService对象TaskService taskService = processEngine.getTaskService();// 设置一些参数,流程定义的key,候选用户String key = "java110_752023081032120386";String candidateUsers = "mps8";List<Task> list = taskService.createTaskQuery().processDefinitionKey(key).taskCandidateGroup(candidateUsers)// 设置候选用户.list();for (Task task : list) {System.out.println(task.getProcessInstanceId());System.out.println(task.getId());System.out.println(task.getName());System.out.println(task.getAssignee());//为null,说明当前的mps7只是一个候选人,并不是任务的执行人(需要拾取任务)}}/*候选用户拾取任务*/@Testvoid claimTask(){// 得到ProcessEngine对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService对象TaskService taskService = processEngine.getTaskService();// 设置一些参数,流程定义的key,候选用户String key = "java110_752023081032120386";String candidateUsers = "mps8";Task task = taskService.createTaskQuery().processDefinitionKey(key)
//                        .taskCandidateUser(candidateUsers)// 设置候选用户(候选用户方式).taskCandidateGroup(candidateUsers)// 设置候选用户(候选用户组方式).singleResult();if (task != null) {taskService.claim(task.getId(), candidateUsers);// 第一个参数任务ID,第二个参数为具体的候选用户名   此处可以try catch下,如果该任务已经被其他人拾取,会报异常,此时可以给前端展示任务已被拾取System.out.println("任务拾取完毕!"); // 拾取完之后就可以正常的进行办理了}}/*任务的退还 和 交接*/@Testvoid connectTask(){// 得到ProcessEngine对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService对象TaskService taskService = processEngine.getTaskService();// 设置一些参数,流程定义的key,用户String key = "java110_752023081032120386";String assignee = "mps7";// 执行查询Task task = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee)  // 设置任务的负责人.singleResult();// 判断是否有这个任务if (task != null) {// 退还 如果设置为null,归还组任务,该任务没有负责人taskService.setAssignee(task.getId(), null);// 交接 交接任务为mps8  ,交接任务就是一个候选人拾取用户的过程 // 注意:activiti没有帮我们限制一定是候选组里面的人,可以交接给任意人
//                        taskService.setAssignee(task.getId(), "lisi");
//                        System.out.println("交接任务完成~!");}}/*任务委派*/@Testvoid delegateTask(){String key = "java110_752023081032120386";String assignee = "mps3";// 得到ProcessEngine对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService对象TaskService taskService = processEngine.getTaskService();// 执行查询Task task = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee)  // 设置任务的负责人.singleResult();// 判断是否有这个任务if (task != null) {taskService.delegateTask(task.getId(),"mps2");}}/*1.claim() 和 setAssignee() 区别taskService.claim(String taskId,String userId);taskService.setAssignee(String taskId, String userId);都可以实现对任务的认领。两个方法的区别在于执行 claim 方法时会检查该任务是否已被签收,如果已被签收,则会抛出 ActivitiTaskAlreadyClaimedException 异常,其他方面两个方法效果一致。2. 委派在act_ru_task表中OWNER_(委托人),ASSIGNEE_(办理人)两个字段。任务委托一定是任务的代理人assignee如mps3将自己的任务委托给用户mps2原来表中:ASSIGNEE_=mps3    OWNER_=null委托后:ASSIGNEE_=mps2    OWNER_=mps3务必理解:OWNER_是委托前的办理人3. 候选用户 和 候选组候选用户和候选组都需要先拾取任何,然后在办理任务。没有用户拾取任务时代办人(Assignee)为空。候选组有更加规范的使用方式,参考:https://blog.csdn.net/qq_41466440/article/details/130592801。*/
}

候选用户,候选用户组,代办人

        /*查询用候选用户,候选用户组*/@Testvoid queryUsersTask(){List<IdentityLink> forTask = taskService.getIdentityLinksForTask(task.getId());for(IdentityLink identityLink : forTask){System.out.println("<------------------候选组用户>");System.out.println("GroupId:"+identityLink.getGroupId());System.out.println("ProcessDefinitionId:"+identityLink.getProcessDefinitionId());System.out.println("TaskId:"+identityLink.getTaskId());System.out.println("UserId:"+identityLink.getUserId());System.out.println("Type:"+identityLink.getType());System.out.println("ProcessInstanceId:"+identityLink.getProcessInstanceId());}}

查询候选用户结果:

<------------------候dai选组用户>
GroupId:null
ProcessDefinitionId:null
TaskId:12503
UserId:mps7
Type:candidate
ProcessInstanceId:null
<------------------候选组用户>
GroupId:null
ProcessDefinitionId:null
TaskId:12503
UserId:mps8
Type:candidate
ProcessInstanceId:null

查询代办用户结果:

GroupId:null
ProcessDefinitionId:null
TaskId:20003
UserId:mps8
Type:assignee
ProcessInstanceId:null

查询候选用户组的结果:

<------------------候选组用户>
GroupId:mps7
ProcessDefinitionId:null
TaskId:20003
UserId:null
Type:candidate
ProcessInstanceId:null
<------------------候选组用户>
GroupId:mps8
ProcessDefinitionId:null
TaskId:20003
UserId:null
Type:candidate
ProcessInstanceId:null

注意:

  1. 返回结果的Type来区分:candidate候选用户,assignee代办用户
  2. 候选组用户这样查询,正常使用。
  3. 候选组有更加规范的使用方式,参考:https://blog.csdn.net/qq_41466440/article/details/130592801
  • 流程变量

流程变量的作用域

  • 全局流程变量:在整个流程执行期间,这个流程变量都是有效的。
  • 本地流程变量:这个只针对流程中某一个具体的 Task(任务)有效,这个任务执行完毕后,这个流程变量就失效了。
  • 临时流程变量:顾名思义就是临时的,这个不会存入到数据库中(略)。

全局变量

  1. 启动流程时设置变量
@Test
void test01() {Map<String, Object> variables = new HashMap<>();variables.put("days", 10);variables.put("reason", "休息一下");variables.put("startTime", new Date());ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01", variables);
}

储存在ACT_RU_VARIABLE表和ACT_HI_VARINST表里面,每一个流程变量都有对应的流程实例 ID,这就说明这些流程变量是属于某一个流程实例的。

@Test
void test01() {List<Execution> list = runtimeService.createExecutionQuery().list();for (Execution execution : list) {Object reason = runtimeService.getVariable(execution.getId(), "reason");}
}
/* sql
: ==> select * from ACT_RU_VARIABLE WHERE EXECUTION_ID_ = ? AND TASK_ID_ is null AND NAME_ = ?
: ==> 6fdd2007-4c3a-11ed-aa7e-acde48001122(String), reason(String)
: <== Total: 1
*/

查询某一个流程的所有变量

@Test
void test02() {List<Execution> list = runtimeService.createExecutionQuery().list();for (Execution execution : list) {Map<String,Object> variables = runtimeService.getVariables(execution.getId());}
}
/* sql
: ==>  select * from ACT_RU_VARIABLE WHERE EXECUTION_ID_ = ? AND TASK_ID_ is null: ==> 6fdd2007-4c3a-11ed-aa7e-acde48001122(String): <== Total: 3*/
  1. 通过 Task 设置
@Test
void test03() {Task task = taskService.createTaskQuery().singleResult();taskService.setVariable(task.getId(), "days", 10); // 逐个设置Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());taskService.setVariables(task.getId(),variables); // 直接设置一个 Map
}
  1. 完成任务时设置
@Test
void test04() {Task task = taskService.createTaskQuery().singleResult();Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());variables.put("days", 10);taskService.complete(task.getId(),variables);
}
  1. 通过流程设置
@Test
void test05() {Execution execution = runtimeService.createExecutionQuery().singleResult();runtimeService.setVariable(execution.getId(), "days", 10); // 逐个设置Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());runtimeService.setVariables(execution.getId(), variables); // 直接设置一个 Map
}

本地变量

  1. 通过 Task 设置
@Test
void test03() {Task task = taskService.createTaskQuery().singleResult();taskService.setVariableLocal(task.getId(), "days", 10); // 逐个设置Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());taskService.setVariableLocal(task.getId(),variables); // 直接设置一个 Map
}

ACT_RU_VARIABLE 表的里的TASK_ID_ 有值字段就要值了。

通过taskService.complete(task.getId());执行完任务后就在ACT_RU_VARIABLE表里面查不到该变量了,需要在历史表里面查询。

@Test
void test07() {ProcessInstance pi = runtimeService.createProcessInstanceQuery().singleResult();List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(pi.getId()).list();for (HistoricVariableInstance hvi : list) {logger.info("name:{},type:{},value:{}", hvi.getVariableName(), hvi.getVariableTypeName(), hvi.getValue());}
}
  1. 完成任务时设置
@Test
void test04() {Task task = taskService.createTaskQuery().singleResult();Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());variables.put("days", 10);taskService.complete(task.getId(),variables,true);
}
/*
complete(java.lang.String, java.util.Map<java.lang.String,java.lang.Object>, boolean):在完成一个 Task 的时候,如果传递了变量,则可以通过第三个参数来控制这个变量是全局的还是本地的,true 表示这个变量是本地的。
*/

后续加的设置变量的方法

  • 设置方法变量
  • ${da.e(qingjiakaishishijian)>da.e(‘2023-08-21’)} 需要这样的e()方法来转换字符串
// 定义一个类
public class Da implements Serializable {public long e(String date) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");try {return format.parse(date).getTime();} catch (ParseException e) {e.printStackTrace();}return 1;}
}// 设置变量HashMap<String, Object> variables = new HashMap<>();Da da = new Da();variables.put("qingjiakaishishijian","2023-08-22");variables.put("da",da);
// 设置到流程当中(也可以用其它方式设置,本例只写启动时设置)ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,variables);

启动流程,带流程map变量时用到的文件

  • bpmn文件(文件局部内容)
  <bpmn2:process id="java110_752023081032120386" name="请假流程-10" isExecutable="true"><bpmn2:startEvent id="StartEvent_1" name="开始"><bpmn2:outgoing>Flow_0gx4dj0</bpmn2:outgoing></bpmn2:startEvent><bpmn2:sequenceFlow id="Flow_0gx4dj0" sourceRef="StartEvent_1" targetRef="Activity_1jdu4q4" /><bpmn2:sequenceFlow id="Flow_01hxak9" sourceRef="Activity_1jdu4q4" targetRef="Activity_0uxetgk" /><bpmn2:sequenceFlow id="Flow_0196722" name="大于等于3天" sourceRef="Activity_0uxetgk" targetRef="Activity_0wbgvlh"><bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">${evection.num&gt;=3}</bpmn2:conditionExpression></bpmn2:sequenceFlow><bpmn2:userTask id="Activity_1jdu4q4" name="提交者" activiti:assignee="${assignee0}"><bpmn2:incoming>Flow_0gx4dj0</bpmn2:incoming><bpmn2:outgoing>Flow_01hxak9</bpmn2:outgoing></bpmn2:userTask><bpmn2:userTask id="Activity_0uxetgk" name="部门经理" activiti:assignee="${assignee1}"><bpmn2:incoming>Flow_01hxak9</bpmn2:incoming><bpmn2:outgoing>Flow_0196722</bpmn2:outgoing><bpmn2:outgoing>Flow_05s60lc</bpmn2:outgoing></bpmn2:userTask><bpmn2:userTask id="Activity_0wbgvlh" name="总经理" activiti:assignee="${assignee2}"><bpmn2:incoming>Flow_0196722</bpmn2:incoming><bpmn2:outgoing>Flow_142455r</bpmn2:outgoing></bpmn2:userTask><bpmn2:sequenceFlow id="Flow_142455r" sourceRef="Activity_0wbgvlh" targetRef="Activity_0su91aq" /><bpmn2:userTask id="Activity_0su91aq" name="财务" activiti:assignee="${assignee3}"><bpmn2:incoming>Flow_142455r</bpmn2:incoming><bpmn2:incoming>Flow_05s60lc</bpmn2:incoming><bpmn2:outgoing>Flow_075zn6w</bpmn2:outgoing></bpmn2:userTask><bpmn2:sequenceFlow id="Flow_05s60lc" name="小于3天" sourceRef="Activity_0uxetgk" targetRef="Activity_0su91aq"><bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">${evection.num&lt;3}</bpmn2:conditionExpression></bpmn2:sequenceFlow><bpmn2:endEvent id="Event_0zvcra4"><bpmn2:incoming>Flow_075zn6w</bpmn2:incoming></bpmn2:endEvent><bpmn2:sequenceFlow id="Flow_075zn6w" sourceRef="Activity_0su91aq" targetRef="Event_0zvcra4" /></bpmn2:process>
  • 图片

在这里插入图片描述

候选用户和候选组的bpmn文件

  • 候选组bpmn(文件局部内容)
<bpmn2:userTask id="Activity_1js1e5x" name="总经理" activiti:candidateGroups="mps7,mps8"><bpmn2:incoming>Flow_0o5ixaf</bpmn2:incoming><bpmn2:outgoing>Flow_192t89v</bpmn2:outgoing>
</bpmn2:userTask>
  • 候选用户bpmn(文件局部内容)
<bpmn2:userTask id="Activity_1js1e5x" name="总经理" activiti:candidateUsers="mps7,mps8"><bpmn2:incoming>Flow_0o5ixaf</bpmn2:incoming><bpmn2:outgoing>Flow_192t89v</bpmn2:outgoing>
</bpmn2:userTask>

排他网关

  1. 设置天数就用带流程map变量的启动流程就行
  2. 也可以在流程当中设置流程变量(参考Global和Local)
  • 图片

在这里插入图片描述

并行网关

  1. 设置天数就用带流程map变量的启动流程就行
  2. 也可以在流程当中设置流程变量(参考Global和Local)
  3. 并行网关的条件不会执行
  4. 并行网关一般都是两个一个分开一个聚合,并行网关两个或多个都执行完成才合并然后往下走

在这里插入图片描述

包含网关

  1. 设置天数就用带流程map变量的启动流程就行
  2. 也可以在流程当中设置流程变量(参考Global和Local)
  3. 包含网关相当于并行和排他的结合体,符合条件的都执行完才会合并然后往下走

在这里插入图片描述

  • 设置天数用到的javaBean类(注意:一定到实现序列化接口)
public class Evection implements Serializable {private double num;public double getNum() {return num;}public void setNum(double num) {this.num = num;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/906764.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golang 对象池sync.Pool的实现

Go语言中sync.Pool通过多级缓存机制实现高效对象复用&#xff0c;其核心设计结合了GMP调度模型特性。以下是实现要点分析&#xff1a; P o o l ∑ p 0 G O M A X P R O C S ( l o c a l P o o l p ) v i c t i m C a c h e Pool \sum_{p0}^{GOMAXPROCS}(localPool_p) vict…

Docker run命令-p参数详解

端口映射基础语法 docker run -p <宿主机端口>:<容器端口> 操作示例 docker run -d --restartalways --namespug -p 5000:80 registry.aliyuncs.com/openspug/spug参数解析 -d&#xff1a;后台运行容器--restartalways&#xff1a;设置容器自动重启--namespug&…

《2.1.4 C语言中的整数类型及类型转换|精讲篇》

后面作者会在2025.5.25 00:00前整理出笔记和思维导图大家放心&#xff0c;主页还有其他文章 请先移步欢迎参考 收藏文章 关注博主 高效学习 好了&#xff0c;这小节我们要探讨一个相对来说简单的问题&#xff0c;就是C语言里边的那些定点整数是如何进行强制类型转换的。好来看这…

采用多维计算策略(分子动力学模拟+机器学习),显著提升 α-半乳糖苷酶热稳定性

字数 978&#xff0c;阅读大约需 5 分钟 在工业应用领域&#xff0c;α-半乳糖苷酶在食品加工、动物营养及医疗等方面发挥着重要作用。然而&#xff0c;微生物来源的该酶往往存在热稳定性不足的问题&#xff0c;限制了其在工业场景中的高效应用。近日&#xff0c;来自江南大学的…

Jetpack Compose预览调试技巧

Jetpack Compose 预览(Preview)不显示是一个常见问题,可能由多种原因导致。以下是系统的调试技巧和解决方案: 1. 检查基础配置 Compose 版本兼容性 确保 compose-compiler、compose-ui 等依赖版本一致且与 Kotlin 版本兼容。检查 build.gradle: android {compileOptions {…

使用 Go 语言实现完整且轻量级高性能的 MQTT Broker

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的发布/订阅消息传输协议。但是目前虽然mqtt的客户端很多&#xff0c;但是服务端着实不多&#xff0c;常见的服务端如mosquitto或emqx。但是golang语言的实现几乎找不到。golang的轻量级部署和高并…

uv sync --frozen卡住不动

今天受邀帮同事调试uv卡住不动的问题&#xff0c;同样的代码已经在别的服务器跑起来了&#xff0c;换了一台服务器之后&#xff0c;执行uv sync --frozen没有按预期创建虚拟环境和安装依赖。 1. 镜像源是已经配置好的&#xff0c;pip install也能很快安装包。 2. 查看了uv.lo…

Spring Boot中如何对密码等敏感信息进行脱敏处理

以下是常见的脱敏方法及实现步骤&#xff0c;涵盖配置、日志和API响应等多个层面&#xff1a; ​1. 配置文件敏感信息脱敏​ (1) 使用加密库&#xff08;如Jasypt&#xff09; ​步骤​&#xff1a; 添加依赖&#xff1a; <dependency><groupId>com.github.ulise…

springboot中redis的事务的研究

redis的事务类似于队列操作&#xff0c;执行过程分为三步&#xff1a; 开启事务入队操作执行事务 使用到的几个命令如下&#xff1a; 命令说明multi开启一个事务exec事务提交discard事务回滚watch监听key(s)&#xff1a;当监听一个key(s)时&#xff0c;如果在本次事务提交之…

python打卡day35@浙大疏锦行

知识点回顾&#xff1a; 三种不同的模型可视化方法&#xff1a;推荐torchinfo打印summary权重分布可视化进度条功能&#xff1a;手动和自动写法&#xff0c;让打印结果更加美观推理的写法&#xff1a;评估模式 作业&#xff1a;调整模型定义时的超参数&#xff0c;对比下效果。…

Python爬虫实战:研究Crawley 框架相关技术

1. Crawley 框架相关定义 1.1 网络爬虫定义 网络爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。它通过 HTTP 协议与 Web 服务器进行交互,获取网页内容并进行解析处理,是数据采集和信息检索的重要工具。 1.2 Crawley 框架定义 Crawley 是一个基于 Pytho…

tvalid寄存器的理解

if(!out_axis_tvalid_reg || m_axis_tready ) beginend m_axis_tready 是上拍下一级给的ready信号 out_axis_tvalid_reg是上一拍&#xff0c;本级给下级的valid信号 一共有四种组合&#xff0c;然后可以通过这个if语句&#xff0c;在接下来的begin ... end中&#xff0c;用来…

【AI实战】从“苦AI”到“爽AI”:Magentic-UI 把“人类-多智能体协作”玩明白了!

Hello&#xff0c;亲爱的小伙伴们&#xff01;你是否曾经在深夜里&#xff0c;为了自动化点外卖、筛机票、抓网页数据焦头烂额&#xff1f;有没有幻想过哪天能出个“贴心AI管家”&#xff0c;一键点菜、搞定事务、自动操作网页&#xff0c;比你还懂你&#xff1f;更关键——还让…

【东枫科技】usrp rfnoc 开发环境搭建

作者 太原市东枫电子科技有限公司 &#xff0c;代理销售 USRP&#xff0c;Nvidia&#xff0c;等产品与技术支持&#xff0c;培训服务。 环境 Ubuntu 20.04 依赖包 sudo apt-get updatesudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils …

Ntfs!ReadIndexBuffer函数分析之根目录读取索引缓冲区的一个例子

Ntfs!ReadIndexBuffer函数分析之根目录读取索引缓冲区的一个例子 第一部分&#xff1a; 0: kd> p Ntfs!ReadIndexBuffer0xdc: f7173962 e829f60300 call Ntfs!NtfsCheckIndexBuffer (f71b2f90) 0: kd> t Ntfs!NtfsCheckIndexBuffer: f71b2f90 55 p…

LumaDot (亮度可调的屏幕圆点)

应用名称 LumaDot &#xff08;源自 “Luminance”&#xff08;亮度&#xff09; “Dot”&#xff08;圆点&#xff09;&#xff0c;强调其核心功能&#xff1a;亮度可调的屏幕圆点&#xff09; 应用说明 LumaDot 是一款轻量级 Windows 桌面工具&#xff0c;专为需要屏幕标记…

HarmonyOS 鸿蒙应用开发基础:EventHub,优雅解决跨组件通信难题

EventHub是鸿蒙开发中用于线程内通信的事件中心模块&#xff0c;基于发布订阅模式实现组件间的高效通信。它完美解决了传统回调方式在多层嵌套场景下的痛点&#xff0c;使得组件间的通信更加灵活和易于管理。 核心特性 事件中心机制&#xff1a;通过事件名进行通信&#xff0c…

前端框架token相关bug,前后端本地联调

今天我搭建框架的时候&#xff0c;我想请求我自己的本地&#xff01;然后我自己想链接我自己的本地后端&#xff0c;我之前用的前端项目&#xff0c;都是链别人的后端&#xff0c;基本上很少情况会链接自己的后端&#xff01;所以我当时想的是&#xff0c;我前后端接口一样&…

【数据结构初阶】顺序表专题

文章目录 顺序表1.数据结构相关概念1、什么是数据结构2、为什么需要数据结构&#xff1f; 2.顺序表1、顺序表的概念及结构2、顺序表分类3、动态顺序表的实现1.定义一个动态顺序表2.顺序表的初始化3.顺序表的销毁4.顺序表达的尾插5.顺序表的头插6.空间大小检查函数7.顺序表的尾删…

从神经生物学到社会心理学:游戏沉迷机制的深度解构

你是否曾在深夜放下手机时惊觉&#xff1a;"明明只想玩10分钟&#xff0c;怎么天都亮了&#xff1f;"这不是意志力薄弱的表现&#xff0c;而是价值数十亿美元的游戏产业用神经科学精心设计的认知陷阱。 当《王者荣耀》的Victory音效让你心跳加速&#xff0c;当《原神…