Activiti笔记以及常遇bug

一、集成activiti

  1. 创建maven工程

在idea中创建maven工程

  1. 添加依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<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>
    <!--druid连接池依赖-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.21</version>
    </dependency>
    <!--添加activiti和SpringBoot整合的依赖
             MyBatis版本会有冲突,所以需要排除-->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring-boot-starter</artifactId>
        <version>7.0.0.SR1</version>
    </dependency>
</dependencies>
  1. 添加配置文件

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///activitiTest?serverTimezone=GMT%2B8 #serverTimezone=GMT%2B8设置时区,防止时区不一致导致连接数据库报错  
    username: root
    password: admin
# 日志配置
logging:
  level:
    org.activiti: debug
  1. 创建启动类

package cn.wolfcode.activiti;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
        System.out.println("启动成功...");
    }
}
  1. 测试【无报错则直接执行下一步】

  1. 出现报错:org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processDeployedEventProducer' defined in class path resource [org/activiti/spring/boot/ProcessEngineAutoConfiguration.class]

  1. 原因:没有配置数据源,在创建项目的时候导入了连接数据库的依赖,这里还没有配置上数据源

  1. 解决方案:给mysql-connector-java设置版本

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
    <scope>runtime</scope>
</dependency>
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-02-06 18:04:17.332 ERROR 15128 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processDeployedEventProducer' defined in class path resource [org/activiti/spring/boot/ProcessEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'processDeployedEventProducer' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'repositoryServiceBean' defined in class path resource [org/activiti/spring/boot/ProcessEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'repositoryServiceBean' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngine': FactoryBean threw exception on object creation; nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'activiti71.act_ge_property' doesn't exist
### The error may exist in org/activiti/db/mapping/entity/Property.xml
### The error may involve org.activiti.engine.impl.persistence.entity.PropertyEntityImpl.selectProperty-Inline
### The error occurred while setting parameters
### SQL: select * from ACT_GE_PROPERTY where NAME_ = ?
### Cause: java.sql.SQLSyntaxErrorException: Table 'activiti71.act_ge_property' doesn't exist
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:538) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at cn.wolfcode.App.main(App.java:9) ~[classes/:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'repositoryServiceBean' defined in class path resource [org/activiti/spring/boot/ProcessEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'repositoryServiceBean' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngine': FactoryBean threw exception on object creation; nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'activiti71.act_ge_property' doesn't exist
### The error may exist in org/activiti/db/mapping/entity/Property.xml
### The error may involve org.activiti.engine.impl.persistence.entity.PropertyEntityImpl.selectProperty-Inline
### The error occurred while setting parameters
### SQL: select * from ACT_GE_PROPERTY where NAME_ = ?
### Cause: java.sql.SQLSyntaxErrorException: Table 'activiti71.act_ge_property' doesn't exist
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:538) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ... 20 common frames omitted
  1. 查看数据库中的表

本应有25张表,由于配置文件中没有加关于历史的配置,则不会生成关于历史的表

表的明细需要知道,有利于开发
  1. 进行测试【前提先绘制流程图,再进行部署】

  1. 流程部署

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ActivitiTest {
    @Autowired
    private RepositoryService repositoryService;


    //部署流程[每次部署都会生成一个部署流程]
    @Test
    public void test01(){
        Deployment deployment = repositoryService
                .createDeployment()                         //创建一个流程
                .addClasspathResource("bpnm/leave.bpmn")    //添加一个配置文件
                .addClasspathResource("bpnm/leave.png")     //添加一个配置文件
                .name("请求流程")                           //设定部署流程的名称
                .deploy();                                  //进行部署
        //输出部署的一些信息
        System.out.println("流程部署/定义ID:"+deployment.getId());
        System.out.println("流程部署名称:"+deployment.getName());
    }
}
  1. 报错:java.lang.NullPointerException

java.lang.NullPointerException
    at cn.wolfcode.ActivitiTest.test01(ActivitiTest.java:19)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
...
  1. 解决方案

解决方案一:添加注解
@SpringBootTest
@RunWith(SpringRunner.class)

解决方案二:更换@Test包:import org.junit.jupiter.api.Test;
  1. 启动流程

    //启动流程[启动的是最新的流程]
    @Autowired
    private RuntimeService runtimeService;        //使用运行服务
    @Test
    public void test02(){
        //定义流程的key[key要与创建的流程图id一致]
        String proecessDefinitionKey = "leave";
        //启动流程实例[调用运行服务来启动流程实例]
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(proecessDefinitionKey);

        //打印流程实例中的信息
        System.out.println("流程定义的key:" + processInstance.getProcessDefinitionKey());
        System.out.println("流程实例的id:" + processInstance.getId());   //在act_ru_task表中进行查看
    }
  1. 查看代办任务

@Autowired
private TaskService taskService;    //使用任务服务
@Test
public void test03(){
    //设置任务负责人
    String assignee = "张三";
    //根据任务负责人获取待办任务
    List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
            .taskAssignee(assignee)                     //根据任务负责人查询
            .list();                                    //获取查询结果集合
    //获取代办任务的信息
    for (Task task : tasks) {
        System.out.println("流程定义id:"  + task.getProcessDefinitionId());
        System.out.println("流程实例id:"  + task.getProcessInstanceId());
        System.out.println("任务id:"  + task.getId());
        //流程是具有起点和终点的与逻辑相关的任务和决策的组合,
        //而任务由机器或人执行的操作步骤组成,其目标是使案例从流程的一个阶段移动到下一个阶段
        System.out.println("任务name:"  + task.getName());
    }
}
  1. 完成任务

//任务处理
/*@Autowired
private TaskService taskService;*/    //使用的依旧是任务服务
@Test
public void test04(){
    //设置任务负责人
    String assignee = "张三";
    //根据任务负责人获取待办任务
    List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
            .taskAssignee(assignee)                     //根据任务负责人查询
            .list();                                    //获取查询结果集合
    //获取代办任务的信息,进行完成任务
    for (Task task : tasks) {
        taskService.complete(task.getId());     //根据任务id完成任务
    }
}
  1. 报错

org.activiti.engine.ActivitiException: In order to use comments, history should be enabled
    at org.activiti.engine.impl.persistence.entity.CommentEntityManagerImpl.checkHistoryEnabled(CommentEntityManagerImpl.java:162) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.persistence.entity.CommentEntityManagerImpl.insert(CommentEntityManagerImpl.java:50) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.persistence.entity.CommentEntityManagerImpl.insert(CommentEntityManagerImpl.java:32) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.cmd.AddCommentCmd.execute(AddCommentCmd.java:105) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.cmd.AddCommentCmd.execute(AddCommentCmd.java:32) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.CommandInvoker$1.run(CommandInvoker.java:37) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:78) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:57) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:42) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:48) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:59) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47) ~[activiti-spring-7.0.0.SR1.jar:na]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45) ~[activiti-spring-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:35) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:44) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:39) ~[activiti-engine-7.0.0.SR1.jar:na]
    at org.activiti.engine.impl.TaskServiceImpl.addComment(TaskServiceImpl.java:334) ~[activiti-engine-7.0.0.SR1.jar:na]
    at cn.wolfcode.ActivitiTest.test05(ActivitiTest.java:102) ~[test-classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686) ~[junit-platform-commons-1.6.2.jar:1.6.2]
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71) ~[junit-jupiter-engine-5.6.2.jar:5.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) ~[junit-platform-engine-1.6.2.jar:1.6.2]
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248) ~[junit-platform-launcher-1.6.2.jar:1.6.2]
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211) ~[junit-platform-launcher-1.6.2.jar:1.6.2]
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226) ~[junit-platform-launcher-1.6.2.jar:1.6.2]
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199) ~[junit-platform-launcher-1.6.2.jar:1.6.2]
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132) ~[junit-platform-launcher-1.6.2.jar:1.6.2]
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69) ~[junit5-rt.jar:na]
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) ~[junit-rt.jar:na]
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230) ~[junit-rt.jar:na]
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58) ~[junit-rt.jar:na]

2023-02-06 20:01:07.783 DEBUG 39256 --- [           main] o.a.e.impl.interceptor.LogInterceptor    : --- AddCommentCmd finished --------------------------------------------------------
2023-02-06 20:01:07.783 DEBUG 39256 --- [           main] o.a.e.impl.interceptor.LogInterceptor    : 
  1. 原因:【为了使用comments,应该启用历史记录】没有使用history

  1. 解决方案:在配置文件中添加activiti配置,修改数据库的url,清空数据库,然后重新部署,重新运行所有测试类

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///activiti71?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false&nullCatalogMeansCurrent=true
    #如果需要获取指定数据库信息,在连接后nullCatalogMeansCurrent属性,由原来的默认true改为了false,nullCatalogMeansCurrent = true,不添加时是在整个数据库在进行检测
    username: root
    password: admin
  activiti:
    database-schema-update: true        #配置项可以设置流程引擎启动和关闭时数据库执行的策略
    db-history-used: true               #数据库是否使用历史
    history-level: full                 #对于历史记录报错的报错程度
    #对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:
    #none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
    #activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
    #audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
    #full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
    check-process-definitions: false    #是否检查流程定义
    use-strong-uuids: false             #是否使用UUID作为主键生成策略

参考来源:简书

链接:https://www.jianshu.com/p/ef3561791f27

  1. 完成任务时进行审批

//添加审批意见
/*@Autowired
private TaskService taskService;*/
@Test
public void test05(){
    //设置任务负责人
    String assignee = "李四";
    //根据任务负责人获取待办任务
    List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
            .taskAssignee(assignee)                     //根据任务负责人查询
            .list();                                    //获取查询结果集合
    //获取代办任务的信息,进行完成任务
    for (Task task : tasks) {
        taskService.addComment(task.getId(),task.getProcessInstanceId(),task.getName()+"审批通过");     //act_hi_comment
        taskService.complete(task.getId());
    }
}
  1. 查看历史任务

//查看历史审批
@Autowired
private HistoryService historyService;
@Test
public void test06(){
    //流程实例Id
    String proecessDefinitionId = "2501";
    //任务审核人
    String assignee = "李四";
    //任务类型
    String act_type = "userTask";
    List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(proecessDefinitionId)
            .activityType(act_type)
            .taskAssignee(assignee)
            .list();

    for (HistoricActivityInstance activityInstance : historicActivityInstances) {
        System.out.println("任务名称 = " + activityInstance.getActivityName());
        System.out.println("任务开始时间 = " + activityInstance.getStartTime());
        System.out.println("任务结束时间 = " + activityInstance.getEndTime());
        System.out.println("任务耗时 = " + activityInstance.getTime());
        //查询历史任务批注本应时HistoryService
        //this interface and its implementations are going to be removed in future iterationsComments doesn't belong to the Process/Task Runtime
        List<Comment> taskComments = taskService.getTaskComments(activityInstance.getTaskId());
        if (taskComments.size() > 0) {
            System.out.println("审批批注 = " + taskComments.get(0).toString());
        }
    }

}
获取审批批注,本应是在历史记录服务(historyService),但实际在taskService中,使用时需要注意

二、activiti进阶

  1. 流程定义的查询[使用repositoryService的API]

    //流程定义的查询
    @Test
    public void test11() {
        //定义流程的key[key要与创建的流程图id一致]
        String proecessDefinitionKey = "leave";
        //查询流程实例[调用运行服务来查询流程实例]
        List<ProcessDefinition> processDefinitions = repositoryService
                .createProcessDefinitionQuery()
                .processDefinitionKey(proecessDefinitionKey)
                .list();

        //打印流程实例中的信息
        for (ProcessDefinition definition : processDefinitions) {
            System.out.println("流程定义ID:" + definition.getId());
            System.out.println("流程定义名称:" + definition.getName());
            System.out.println("流程定义key:" + definition.getKey());
            System.out.println("流程定义版本:" + definition.getVersion());
            System.out.println("流程部署ID:" + definition.getDeploymentId());
            System.out.println("====================");
        }
    }

  1. 下载资源[使用repositoryService的API]

//下载资源
@Test
public void test01() throws Exception {
    String deploymentId = "1";      //流程定义id
    String resourceName = "bpnm/leave.png";
    InputStream resourceAsStream = repositoryService
            .getResourceAsStream(deploymentId, resourceName);
    FileOutputStream outputStream = new FileOutputStream("D:\\leave.png");
    IOUtils.copy(resourceAsStream,outputStream);
}

流程资源文件已经上传到数据库,如果其他用户想要查看这些资源文件,可以从数据库中下载到本地。

  1. 流程定义删除

根据部署Id删除对应的流程定义[若流程仅只是部署,则可以删除]

//删除流程
@Test
public void test02(){
    //定义流程的key[key要与创建的流程图id一致]
    String deploymentId = "1";
    //删除流程定义,如果该流程定义已有流程实例启动则删除时出错
    repositoryService.deleteDeployment(deploymentId);
}

[若流程已经启动,则删除时会报错]

org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`activiti71`.`act_ru_execution`, CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`))
### The error may involve org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl.deleteProcessDefinitionsByDeploymentId-Inline
### The error occurred while setting parameters
### SQL: delete from ACT_RE_PROCDEF where DEPLOYMENT_ID_ = ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`activiti71`.`act_ru_execution`, CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`))

解决方案:

  • 方案一:设置级联删除流程定义

//删除流程
@Test
public void test02(){
    //定义流程的key[key要与创建的流程图id一致]
    String deploymentId = "10001";
    //设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式
    repositoryService.deleteDeployment(deploymentId,true);
}
  • 方案二:先删除流程实例,再删除流程

说明:

1) 流程定义下没有正在运行的流程,可以用普通删除。

2) 流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关记录全部删除。

3) 项目开发中级联删除操作一般只开放给超级管理员使用。

  1. 流程实例相关

  • 定义:按照流程定义内容发起一个流程,这个流程就是一个流程实例

  • BusinessKey(业务标识)

案例:

  1. 小张要在5.1~5.10这段时间请假,请假理由为:回家相亲.

  1. 小陈要在5.5~5.15这段时间请假,请假理由为:家里拆迁,回家办手续.

将申请人的请假时间和请假信息如何绑定到流程中

  • 启动流程实例时,指定的businessKey,就会在act_run_execution表中存储businessKey。

  • BusinessKey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。

  • 比如:请假流程启动一个流程实例,就可以将请假单的id作为业务标识存储到Activiti中,将来查询Activiti的流程实例信息就可以获取请假单的id从而关联查询业务系统数据库得到请假单信息。

  • 设置businessId

测试实现

//开启流程实例服务
@Autowired
private RuntimeService runtimeService;
@Test
public void test03(){
    //定义业务id
    String businessKey = "1";
    //定义进程key
    String processDefineKey="leave";
    //在创建流程实例时将业务id设置进去
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefineKey, businessKey);
    //获取流程实例的相关信息
    System.out.println("流程定义的id = " + processInstance.getProcessDefinitionId());
    System.out.println("流程实例的id = " + processInstance.getId());

}

结果:

  • 如何获取流程实例绑定的业务信息

//如何获取流程实例绑定的业务信息
@Autowired
private TaskService taskService;
@Test
public void test04(){
    String assignee = "张三";
    List<Task> tasks = taskService.createTaskQuery()
            .taskAssignee(assignee)
            .list();
    for (Task task : tasks) {
        System.out.println("流程定义id = " + task.getProcessDefinitionId());
        System.out.println("流程实例id = " + task.getProcessInstanceId());
        System.out.println("任务id = " + task.getId());
        System.out.println("任务名称 = " + task.getName());
        //根据任务上的流程实例Id查询出对应的流程实例对象,从流程实例对象中获取BusinessKey
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
        System.out.println("业务key:"+instance.getBusinessKey());    //获取业务key
        System.out.println("===================");
    }
}

  1. 流程定义/实例挂起/激活

  • 单个流程挂起场景:例如公司制度改变过程中的流程, 总经理更换过程中的流程,有100个人的流程, 70个人已经完成,30个人流程正好在总经理更换中,就需要挂起

  • 【开始节点】-->【A节点】-->【B节点】-->【C节点】-->【结束节点】

  • 【C节点】的业务逻辑需要和外部接口交互,刚好外部接口出问题了,如果剩下的流程都走到【C节点】,执行【C节点】的业务逻辑,那都会报错,我们就可以把流程挂起,等待外部接口可用之后再重新激活流程.

  • 业务流程发生改变,已经发起的流程实例继续按照旧的流程走,如果新发起的流程就按照新的业务流程走.这时候我们就需要挂起流程定义,但是不挂起流程实例

  • 实例挂起测试

@Test
public void testSuspendAllProcessInstance(){
    //流程定义key
    String processDefinitionKey="leave";
    //获取流程定义对象
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(processDefinitionKey)
            .singleResult();
    boolean suspended = processDefinition.isSuspended();    //获取状态
    System.out.println("流程定义状态:"+(suspended ?"已挂起":"已激活"));
    String processDefinitionId = processDefinition.getId();     //获取流程定义Id
    if(suspended){
        //如果是挂起,可以执行激活操作 ,参数1 :流程定义id ,参数2:是否激活流程实例,参数3:激活时间
        repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
        System.out.println("流程ID:"+processDefinitionId+",已激活");
    }else {
        //如果是激活,可以执行挂起操作 ,参数1 :流程定义id ,参数2:是否暂停流程实例,参数3:激活时间
        repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
        System.out.println("流程ID:"+processDefinitionId+",已挂起");
    }
}

挂起状态时不允许启动流程、执行任务,会报错

org.activiti.engine.ActivitiException: Cannot start process instance. Process definition null (id = leave:1:15004) is suspended

    at org.activiti.engine.impl.util.ProcessInstanceHelper.createAndStartProcessInstance(ProcessInstanceHelper.java:61)
    at org.activiti.engine.impl.util.ProcessInstanceHelper.createAndStartProcessInstance(ProcessInstanceHelper.java:50)
    at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.createAndStartProcessInstance(StartProcessInstanceCmd.java:109)
    at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:102)
    at org.activiti.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:37)
    at org.activiti.engine.impl.interceptor.CommandInvoker$1.run(CommandInvoker.java:37)
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:78)
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:57)
....
  • 单个流程实例挂起场景:

  • 评分流程:可设置多级评分,评分流程会按照从上往下的顺序,依次评分;评分人必须在评分截至时间内完成评分,否则不允许继续评分,流程将会挂起,停止流转;

  • 操作流程实例对象,针对单个流程执行挂起操作,某个流程实例挂起则此流程不再执行,完成该流程实例的当前任务将报异常。

//查看所有流程实例
@Test
public void test06() {
    String processDefineKey = "leave";
    List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery()
            .processDefinitionKey(processDefineKey)
            .list();
    for (ProcessInstance processInstance : processInstances) {
        System.out.println("流程实例Id:" + processInstance.getId() + ",状态:" + (processInstance.isSuspended() ? "已挂起" : "已激活"));
    }
}

//挂起单个流程实例
@Test
public void test07() {
    String processInstanceId = "22501";    //定义流程实例Id
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
            .processInstanceId(processInstanceId)    //根据流程实例Id
            .singleResult();    //获取单个结果
    boolean suspended = processInstance.isSuspended();        //获取流程对象
    System.out.println("流程实例ID:" + processInstance.getId() + ",状态:" + (suspended ? "已挂起" : "已激活"));
    if (suspended) {
        runtimeService.activateProcessInstanceById(processInstanceId);  //激活流程实例
        System.out.println("流程实例ID:" + processInstanceId + ",状态修改为已激活");
    } else {
        runtimeService.suspendProcessInstanceById(processInstanceId);   //修改流程实例状态
        System.out.println("流程实例ID:" + processInstanceId + ",状态修改为已挂起");
    }
}

  1. 任务分配负责人

  • 方式一:直接在绘制bpmn图时直接在assigner中进行设置【这里也可以填写UEL 表达式

  • 方式二:使用UEL 表达式, UEL 是 java EE6 规范的一部分, UEL(Unified Expression Language)即 统一表达式语言。

注意:修改Assignee存在bug,在界面上修改了,但是实际文件并没有修改.所以我们需要借助编辑工具在xml文件中修改一下Assignee

  1. 流程变量

  • 流程变量定义:

  • Activiti在管理工作流时根据管理需要而设置的变量,可以满足设计者设计时:该环节要满足某项条件才执行。

  • 比如在请假流程流转时如果请假天数>3天则有总经理审批,否则由人事直接审批,请假天数就可以设置流程变量,在流程流转时使用。

注意:虽然流程变量中可以存储业务数据,可以通过Activiti的API查询流程变量从而实现查询业务数据,但是不建议这么使用,因为业务数据查询由业务系统负责,Activiti设置流程变量是为了流程执行需要而创建的。

  • 类型【string,Integer,short,long,double,boolean,date,binary,serializable】

注意:如果将POJO存储到流程变量中,必须实现序列化接口Serializable,为了防止由于新增字段无法反序列化。

  • 作用域

作用域范围:流程变量的作用域范围可以是一个流程实例(ProcessInstance)、一个任务(Task)或一个执行实例(Execution)。

global变量: 流程变量的作用域范围的默认值是流程实例,作用域范围最大。
local变量 : 流程变量的作用域范围如果仅仅针对一个任务或一个执行实例,那么作用域范围没有流程实例大【一般不用】

  • 使用方法

  • 在属性上使用UEL表达式

可以在 assignee 处设置 UEL 表达式,表达式的值为任务的负责人,比如: ${assignee}, assignee 就是一个流程变量名称。

Activiti相关方法获取UEL表达式的值,即流程变量assignee的值 ,将assignee的值作为任务的负责人进行任务分配

  • 在连线上使用UEL表达式

可以在连线上设置UEL表达式,决定流程走向。UEL表达式结果类型为布尔类型。如果UEL表达式是true,要决定 流程执行走向。

  • 使用global变量控制流程

@SpringBootTest
public class VariablesTest {
    @Autowired
    private RepositoryService repositoryService;

    //部署流程【数据会存储在act_re_deployment表中,每次部署都会添加一个流程】
    @Test
    public void test01(){
        Deployment deployment = repositoryService
                .createDeployment()                         //创建一个流程
                .addClasspathResource("bpnm/leave.bpmn")    //添加一个配置文件
                //.addClasspathResource("bpnm/leave.png")     //添加一个配置文件
                .name("请求流程")                           //设定部署流程的名称
                .deploy();                                  //进行部署
        //输出部署的一些信息
        System.out.println("流程部署ID:"+deployment.getId());
        System.out.println("流程部署名称:"+deployment.getName());
    }

    //启动流程[启动的是最新的]
    @Autowired
    private RuntimeService runtimeService;
    @Test
    public void test02(){
        //定义流程的key[key要与创建的流程图id一致]
        String proecessDefinitionKey = "leave";
        //设置variables
        Map<String, Object> variables = new HashMap<>();
        variables.put("manager","小莉");
        variables.put("hr","lili");
        variables.put("president","lala");
        variables.put("day",10);
        //启动流程实例[调用运行服务来启动流程实例]
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(proecessDefinitionKey,variables);

        //打印流程实例中的信息
        System.out.println("流程定义的key:" + processInstance.getProcessDefinitionKey());
        System.out.println("流程实例的id:" + processInstance.getId());   //在act_ru_task表中进行查看
    }

    //查看代办任务
    @Autowired
    private TaskService taskService;
    @Test
    public void test03(){
        //设置任务负责人
        String assignee = "小莉";
        //根据任务负责人获取待办任务
        List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
                .taskAssignee(assignee)                     //根据任务负责人查询
                .list();                                    //获取查询结果集合
        //获取代办任务的信息
        for (Task task : tasks) {
            System.out.println("流程定义id:"  + task.getProcessDefinitionId());
            System.out.println("流程实例id:"  + task.getProcessInstanceId());
            System.out.println("任务id:"  + task.getId());
            //流程是具有起点和终点的与逻辑相关的任务和决策的组合,
            //而任务由机器或人执行的操作步骤组成,其目标是使案例从流程的一个阶段移动到下一个阶段
            System.out.println("任务name:"  + task.getName());
        }
    }

    //任务处理
    /*@Autowired
    private TaskService taskService;*/
    @Test
    public void test04(){
        //设置任务负责人
        String assignee = "小莉";
        //根据任务负责人获取待办任务
        List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
                .taskAssignee(assignee)                     //根据任务负责人查询
                .list();                                    //获取查询结果集合
        //获取代办任务的信息,进行完成任务
        for (Task task : tasks) {
            taskService.complete(task.getId());     //根据任务id完成任务
        }
    }
    //任务处理
    /*@Autowired
    private TaskService taskService;*/
    @Test
    public void test05(){
        //设置任务负责人
        String assignee = "lala";
        //根据任务负责人获取待办任务
        List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
                .taskAssignee(assignee)                     //根据任务负责人查询
                .list();                                    //获取查询结果集合
        //获取代办任务的信息,进行完成任务
        for (Task task : tasks) {
            taskService.complete(task.getId());     //根据任务id完成任务
        }
    }
    //任务处理
    /*@Autowired
    private TaskService taskService;*/
    @Test
    public void test06(){
        //设置任务负责人
        String assignee = "lili";
        //根据任务负责人获取待办任务
        List<Task> tasks = taskService.createTaskQuery()   //创建查询的任务
                .taskAssignee(assignee)                     //根据任务负责人查询
                .list();                                    //获取查询结果集合
        //获取代办任务的信息,进行完成任务
        for (Task task : tasks) {
            taskService.complete(task.getId());     //根据任务id完成任务
        }
    }
}
注意:
1.UEL表达式中流程变量名不存在则报错。
2.UEL表达式都不符合条件,流程报错。
3.连接不设置条件/条件都满足,每个连线都会走.
  1. 网关

  • 排他网关(ExclusiveGateway)(异或网关或基于数据的排他网关),用来在流程中实现决策。当流程执行到这个网关的时候,所有分支都会判断条件是否为true,如果为true则执行该分支。

注意:排他网关只会选择一个为true的分支执行(即使有两个分支条件都为true,排他网关也只会选择一条分支去执行,选择序号小的路径执行)。

  • 并行网关(InclusiveGateway)允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进入和外出的顺序流的。

并行网关不会解析条件。即使顺序流中定义了条件,也会被忽略

  • 包含网关可以看做是排他网关和并行网关的结合体。

三、在项目中集成activiti

  1. 导入依赖

<!--添加activiti和SpringBoot整合的依赖
     MyBatis版本会有冲突,所以需要排除-->
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.0.0.SR1</version>
</dependency>
  1. 启动项目

@SpringBootApplication
@MapperScan(basePackages = "cn.wolfcode.mapper")
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }
}
  • 遇到问题

问题:使用postman进行访问时,访问超时

原因:Spring Boot 集成的 Activiti 依赖 activiti-spring-boot-starter 中 ,同时也集成了 Security 框架,所以说它可谓是自带权限控制功能

解决方案:进行security的相关配置

  • 获取所有Businesskey

//查询了很多信息没有找到获取所有Businesskey的方法,所以使用以下方法来实现

//查询所有任务
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
//创建一个新的集合list
List<String> businessKeys = new ArrayList<>();
list.forEach(v -> businessKeys.add(v.getBusinessKey()));
return businessKeys;
  • 集成时遇到的问题:返回json数据给前端,前端获取不到

[该内容参考原文链接https://blog.csdn.net/yage124/article/details/103176405]

原因:打开activiti的一个实体类org.activiti.engine.task,如下所示,并不像我们平时的实体类,get和set方法在一个类中,他是分不同种的接口,可能就是由于这个原因使得无法返回json格式数据。

解决方案:将返回结果封装到Map集合中进行返回

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值