2.通过zip压缩包部署

发布时间:2025-06-24 20:38:44  作者:北方职教升学中心  阅读量:970


与Activiti7的区别

1.Activiti默认不开启数据库的历史记录,flowable默认开启

2.Activiti23张表,flowable79张表。

2.表结构
  • act_re: repository,包含流程定义和流程静态资源(图片,规则等)

  • act_ru: runtime,运行时的表,包含实例,任务,变量,异步任务,运行中的数据等

  • act_hi:history,流程的历史数据,如历史流程实例,变量,任务。

    一、

  • 流程定义与流程部署是不一样的,一个流程部署可以对应多个流程定义。

    5.流程变量
    1. 运行时变量

      全局变量

      局部变量

    2. 历史变量

      @Test    void startFlow(){        String processId="firstFlow:2:637173cf-1ce6-11ef-8399-005056c00008";        //在流程启动时就可以绑定对应表达式的值,因为第一个人就需要指定人        Map<String,Object> variables =new HashMap<>();        variables.put("var1","test1");        variables.put("var2","test2");        variables.put("var3","test3");        //全局变量存在了act_ru_variable        runtimeService.startProcessInstanceById(processId,variables);    }    /**     * 获取流程全局变量     */    @Test    //全局变量存在了act_ru_variable    void getVariables(){        String execution ="06a934bf-1ce7-11ef-870f-005056c00008";        //还能直接设置        //runtimeService.setVariable(execution,"var4","test4");        //设置局部变量,和taskId相关,节点没了变量就没了        //runtimeService.setVariablesLocal(execution,"var4","test4");        Map<String, Object> variables = runtimeService.getVariables(execution);        System.out.println(variables);    }

    输出{var3=test3, var2=test2, var1=test1}

    6.候选人

    可以指定多个候选人,在启动流程时进行赋值就好。

     /**     * 当前登录用户根据候选人组查询任务     */    @Test    void findGroupTask(){        //先查询当前所在的组 如查张三        Group group = identityService.createGroupQuery()                .groupMember("zhangsan").singleResult();        System.out.println("当前用户所在组的id为:"+group.getId());        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(group.getId()).list();        for (Task task : tasks) {            //拾取任务            taskService.claim(task.getId(),"zhangsan");        }    }        /**     * 任务的审批     */    @Test    void compeleteTask(){        Map<String,Object> variables =new HashMap<>();        taskService.complete("ae543ec1-1d5f-11ef-a409-005056c00008");    }
    8.网关
    • 排他网关

    • 并行网关

    • 包容网关

    • 事件网关

    排他网关

    在审批的时候加入day天数就能完成请假步骤,从而转向不同的审批人。

    并行网关

    提交申请之后,task表中将会出现两条审批,分别是zhangsan和lisi。

3.流程挂起和激活
/**     * 流程定义的挂起和激活     *act_re_procdef     */    @Test    void suspendedActivity(){        String processDefinitionId="ask_for_leave.bpmn20:1:4";        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()                .processDefinitionId(processDefinitionId)                .singleResult();        //获取当前流程定义的状态        boolean suspended = processDefinition.isSuspended();        if (suspended) {            //挂起-->激活            System.out.println("激活流程");            repositoryService.activateProcessDefinitionById(processDefinitionId);        }else {            //激活-->挂起            System.out.println("挂起流程");            repositoryService.suspendProcessDefinitionById(processDefinitionId);        }    }
  • 已经挂起的流程定义,不允许启动。

  • DMN 表示这都是跟 DMN 协议相关的表。流程部署的表是act_re_deployment,流程定义的表是act_re_procdef。2.通过zip压缩包部署。

  • 方法表达式

    ${ myBean.getAssignee() }

/**     * 任务的审批     * 需要数据:任务id,hashMap  "assign1","lisi"     * 把当前任务分给lisi审批,运行后lisi可以查到待办     */    @Test    void compeleteAssign1(){        HashMap<String, Object> variables = new HashMap<>();        variables.put("assign1","lisi");        //完成任务审批,根据任务id绑定对应表达式的值        taskService.complete("taskId",variables);    }

(act_ru_actinst)出现了lisi

 @Test    void findFlow(){        //任务实例通过TaskService来实现        TaskService taskService = getEngine().getTaskService();        //获取到 act_ru_task中 assignee是lisi的记录        List<Task> tasks = taskService.createTaskQuery()                .taskAssignee("lisi")                .list();        tasks.forEach(System.out::println);        //Task[id=15004, name=second]    }

得到结果Task[id=15004, name=second],此时还需要审批。

4.支持 CMMN 和 DMN 标准

三、然后把表的自动更新关闭,否则会影响性能。

  • 删除流程部署,默认级联删除,正在执行的流程实例也会被删除。

  • CMMN 表示这都是跟 CMMN 协议相关的表。

  • 一个部署对应多个流程定义

    @Test    void deployFlow(){        Deployment deploy = repositoryService.createDeployment()            	//如果再添加部署文件,会部署两次,导致流程定义中出现新版本的流程定义                .addClasspathResource("processes/ask_for_leave.bpmn20.xml")                .name("部署名称")                .deploy();        System.out.println("deploy.getId()="+deploy.getId());    }

    常用:1.通过bpmn部署。SpringBoot项目中引入flowable

    1.配置flowable独立数据源

    flowable:  async-executor-activate: false  #第一次生成后关闭  database-schema-update: true  #保存历史数据级别  history-level: full  #解决乱码  activity-font-name: "宋体"  annotation-font-name: "宋体"  label-font-name: "宋体"  #配置flowable数据源flow:  username: root  password: root  url: jdbc:mysql://localhost:3306/flowable2?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true  driver-class-name: com.mysql.cj.jdbc.Driver  maxPoolSize: 30

    2.创建配置类

    import com.alibaba.druid.pool.DruidDataSource;import lombok.extern.slf4j.Slf4j;import org.flowable.app.spring.SpringAppEngineConfiguration;import org.flowable.spring.boot.EngineConfigurationConfigurer;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;​import javax.sql.DataSource;import java.beans.PropertyVetoException;​/** * 一共有两个配置类,一个是ProcessEngineConfiguration,一个是SpringAppEngineConfiguration * 他们里面都需要重写configure方法来进行配置 * 配置数据源应该在SpringAppEngineConfiguration中设定 * 前者是配置ProcessEngine的,如自动生成表,设置中文,在yml文件中配置的属性便是在此类中读取 */@Configuration@PropertySource("classpath:application-dev.yml")@Slf4j​public class FlowableConfig implements EngineConfigurationConfigurer<SpringAppEngineConfiguration> {​    //读取配置    @Value("${flow.username}")    private String user;    @Value("${flow.password}")    String password;    @Value("${flow.url}")    String jdbcUrl;    @Value("${flow.driver-class-name}")    String driverClass;    @Value("${flow.maxPoolSize}")    int maxPoolSize;​//    @Bean(name = "processEngine")//    public ProcessEngine processEngineConfiguration() throws PropertyVetoException {//        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration();//        cfg.setDataSource(dataSource2());//        cfg.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);//        cfg.setActivityFontName("宋体");//        cfg.setLabelFontName("宋体");//        cfg.setAnnotationFontName("宋体");//        cfg.setAsyncExecutorActivate(false);//        return cfg.buildProcessEngine();//  }​    //配置数据源    public DataSource dataSource2() throws PropertyVetoException {        DruidDataSource dataSource = new DruidDataSource();        dataSource.setUsername(user);        dataSource.setPassword(password);        dataSource.setUrl(jdbcUrl);        dataSource.setDriverClassName(driverClass);        dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolSize);        return dataSource;    }​    @Override    public void configure(SpringAppEngineConfiguration engineConfiguration) {        try {            //把数据源设置进来            engineConfiguration.setDataSource(dataSource2());            log.info("配置flowable数据源成功");        } catch (PropertyVetoException e) {            throw new RuntimeException(e);        }    }}

    注意这里配置的是SpringAppEngineConfiguration,而不是ProcessEngine,否则将出现报错,或者设置单独的数据源失败。

    4.任务分配表达式Assignee

    Assignee也可以写表达式

    • 值表达式

      ${ assign1 },assign1是自己定义的变量。SringBoot整合Flowable

      1.引入依赖

      SpringBoot使用2.7.1,亲测3.3.0不能用,JDK使用1.8

      建议slf4j版本如下,不会报错,太高了报错

      <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>         <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.flowable</groupId>            <artifactId>flowable-spring-boot-starter</artifactId>            <version>6.7.2</version>            <!--关闭自带的权限认证-->             <exclusions>                <exclusion>                    <groupId>org.flowable</groupId>                    <artifactId>flowable-spring-security</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>8.0.21</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid-spring-boot-starter</artifactId>            <version>1.2.1</version>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.13.2</version>            <scope>test</scope>        </dependency><!--        日志-->        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-api</artifactId>            <version>1.7.30</version>        </dependency>        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-log4j12</artifactId>            <version>2.0.0</version>        </dependency>

      2.安装流程图绘制插件

      Flowable BPMN visualizer

      3.yml配置

      server:  port: 8080spring:  datasource:    driver-class-name: com.mysql.cj.jdbc.Driver    #nullCatalogMeansCurrent=true 设置为只查当前连接的schema库    url: jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true    username: root    password: rootflowable:  #关闭定时任务  async-executor-activate: true  #数据库表与flowable最新表不一致会进行更新  database-schema-update: truelogging:  level:    org:      flowable: debug

      二、

    • act_ge:general,通用数据。

    • FO(FORM)表示这都是跟表单相关的表。

    • 启动一个流程,可以在act_ru_task表中看到对应的记录,该表记录的都是当前待办的记录信息。

      项目启动成功就可以看到自动创建的79张表了。Spring环境下的应用

      1.流程部署与启动
      @Autowired    ProcessEngine processEngine;    @Autowired    RepositoryService repositoryService;    @Autowired    RuntimeService runtimeService;    @Autowired    TaskService taskService;    @Test    void deployFlow(){        //流程引擎的配置对象,关联相关数据源        Deployment deploy = repositoryService.createDeployment()                //一次部署所有processes文件夹内的流程                .name("第一次部署")                .deploy();        System.out.println("deploy.getId()="+deploy.getId());    }    /**     * 启动流程实例     * 在流程定义表中动态维护 act_re_procdef     */    @Test    void startFlow(){        String processId="ask_for_leave.bpmn20:1:4";        String processKey="ask_for_leave.bpmn20";        //1.根据流程定义di启动流程实例        runtimeService.startProcessInstanceById(processId);        //2.根据流程定义key启动流程实例        //runtimeService.startProcessInstanceByKey(processKey);    }	/**     * 任务的审批     * 需要数据:任务id     */    @Test    void compeleteTask(){        taskService.complete("2506");    }
      • 每启动一个流程,会在act_hi_procinst中维护一条数据。包含标识的信息,如用户,用户组等。

      • 流程定义不需要删除,当你不要这个流程定义时,就把流程部署给删除好了。

      • 已经启动的流程,不受影响。

        act_ge_bytearray(重要),存放了流程定义的png图片。

        /**     * 根据候选人查询任务     * 候选人需要拾取任务才能变成审批人     *只有一个人能变为审批人,审批人还可以归还,变成候选人     */    @Test    void claimTask(){        //act_ru_task中        List<Task> tasks = taskService.createTaskQuery()                //这里有改变                .taskCandidateUser("张三")                .list();        for (Task task : tasks) {            //拾取            taskService.claim(task.getId(),"张三");            //归还unclaim(task.getId(),"张三")            //指派taskService.setAssignee(task.getId(),"xxx")        }    }   @Test    void findFlow(){        //act_ru_task中        List<Task> tasks = taskService.createTaskQuery()                //这里有改变                .taskCandidateUser("张三")                .list();        tasks.forEach(System.out::println);    }
        7.候选人组
        //先创建用户	@Test    void createUser(){        User user = identityService.newUser("zhangsan");        user.setEmail("zhansgan@qq.com");        user.setFirstName("zhang");        user.setLastName("san");        user.setPassword("123456");        identityService.saveUser(user);    }/**     * 用户组     */    @Test    void createGroup(){        Group group = identityService.newGroup("xsb");        group.setName("销售部");        group.setType("type1");        identityService.saveGroup(group);    }/**     * 用户与用户组的关系     */    @Test    void createMemberShip(){        Group group = identityService.createGroupQuery().groupId("xsb").singleResult();        List<User> users = identityService.createUserQuery().list();        users.forEach(user -> {identityService.createMembership(user.getId(), group.getId());});    }

        act_id_group

        act_id_membership

        直接部署后启动,act_ru_identitylink中就会出现候选组信息。

        创建好model之后保存到act_re_model表中(上图仅仅是举个3的例子)。可以理解为act_re_procdef是act_re_deployment的从表。

          @Test    void compeleteTask(){        Map<String,Object> variables =new HashMap<>();        variables.put("day",3);        taskService.complete("fae74a9a-1d6c-11ef-9a09-005056c00008");    }

        注意:条件尽量包含所有情况,否则报错。部署也是先从表中获取model部署。

        3.Flowable是Activiti的继任者,因此Flowable包含了Activiti的所有功能,并且在原有功能的基础上进行了进一步的改进和优化。

      • act_id:identity组织机构。

        ------ 方法表达式${ myBean.getAssignee() } -------

        //MyBean加入容器@Componentpublic class MyBean {    public String getAssignee(){        System.out.println("getAssignee执行...");        return "王五";    }}​
           @Test    void compeleteAssign1(){        TaskService taskService = getEngine().getTaskService();        //再执行审批时,会去MyBean中执行该方法        taskService.complete("15004");    }

        拿到id后再执行审批。3.自己创建model模型,然后保存到数据库中,再通过模型部署。

        包含网关

        可以看成并行和排他的结合体

        如num=2走三条,num=5走两条,num=8走三条

        Tips

        1. 每次重新部署一个id相同的bpmn时,正在执行的流程会被自动删除。

        2. CO(CONTENT)表示这都是跟内容引擎相关的表。

        3. 可以挂起已经启动的流程实例,该流程实例不允许审批。

        4. act_ru_execution记录流程的分支

      流程定义:相当于Java中的类

      流程实例:相当于java中的对象

      注意:在Spring环境下,Spring会自动扫描processes文件夹,若不指定文件路径,则一次把所有bpmn流程全部部署,也就是一次创建所有流程定义。