springboot集成flowable

涉及到的代码地址(前端代码没有PUSH): https://gitee.com/MaoLG/springboot-flowable-demo

1. 服务端集成

1.1 集成依赖

           <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-spring-boot-starter</artifactId>
                <version>6.7.2</version>
            </dependency>

1.2 yml配置

spring:
#数据库链接配置
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
flowable:
#异步执行
  async-executor-activate: true
#自动更新数据库
  database-schema-update: true
#校验流程文件,默认校验resources下的processes文件夹里的流程文件
  process-definition-location-prefix: classpath*:/processes/
  process-definition-location-suffixes: "**.bpmn20.xml, **.bpmn"

1.3 第一次启动创建表

图片.png

1.4 创建的服务端的表

图片.png

1.5 主要几张表介绍

  • ACT_RU_TASK 每次启动的流程都会再这张表中,表示代办项, 流程结束会删除该流程数据
  • ACT_RU_EXECUTION 流程执行过程表, 会存该流程正在执行的过程数据, 流程结束会删除该流程数据
  • ACT_RU_VARIABLE 流程变量表, 流程中传的参数都会再该表存储, 流程结束会删除该流程数据
  • ACT_HI_PROCINST 历史运行流程, 当流程处理完了, 在ACT_RU_* 表中就不会有数据, 可以在该表中查询历史
  • ACT_HI_TASKINST 历史运行的task信息,
  • ACT_RE_PROCDEF 流程模板记录,同一个key多次发布version_字段会递增
  • ACT_RE_DEPLOYMENT 部署的流程模板, 可以启动流程使用的

1.6 部署一个流程

  • controller
package com.example.springbootflowabledemo.controller;

import com.example.springbootflowabledemo.service.FlowableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/flowable-demo")
public class FlowableController {

    @Autowired
    private FlowableService flowableService;

    @PostMapping("/deploy")
    public String deploy(MultipartFile file) throws Exception {
        flowableService.deployment(file.getName(), file.getInputStream());
        return "流程部署成功!";
    }
}
  • service
package com.example.springbootflowabledemo.service.impl;

import com.example.springbootflowabledemo.service.FlowableService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;

@Slf4j
@Service
public class FlowableServiceImpl implements FlowableService {


    @Autowired
    private RepositoryService repositoryService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deployment(String name, InputStream in) {
        Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).deploy();
        log.info("流程部署id={}", deploy.getId());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        log.info("(启动流程使用)流程processDefinitionId={}", processDefinition.getId());
    }
}

1.7 启动一个流程

  • req
package com.example.springbootflowabledemo.domian.req;

import lombok.Data;

import java.util.Map;

@Data
public class ActivateReq {
    private String procdefId;
    private Map<String, Object> variables;
}
  • controller
@PostMapping("/activate")
    public String activate(@RequestBody ActivateReq req) {
        flowableService.activate(req.getProcdefId(), req.getVariables());
        return "流程启动成功!";
    }
  • service
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;

    @Override
    public void activate(String procdefId, Map<String, Object> variables) {
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procdefId, variables);
        log.info("流程id={}", processInstance.getId());

        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
        for (Task task : tasks) {
            log.info("流程id={}, 下次执行task={}", processInstance.getId(), task.getId());
        }
    }

1.8处理节点

  • req
package com.example.springbootflowabledemo.domian.req;

import lombok.Data;

import java.util.Map;

@Data
public class CompleteReq {
    private String taskId;
    private Map<String, Object> variables;
}
  • controller
@PostMapping("/complete")
    public String complete(@RequestBody CompleteReq req) {
        flowableService.complete(req.getTaskId(), req.getVariables());
        return "节点处理完成!";
    }
  • service
   @Override
    public void complete(String taskId, Map<String, Object> variables) {
        taskService.complete(taskId, variables);
    }

2. 客户端集成

2.1 集成依赖

            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-ui-modeler-rest</artifactId>
                <version>6.7.2</version>
            </dependency>
            <!--添加flowable-ui-modeler配置依赖项-->
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-ui-modeler-conf</artifactId>
                <version>6.7.2</version>
            </dependency>

2.2 解决添加依赖报错

  • 问题1

Caused by: java.lang.IllegalArgumentException: flowable.common.app.idm-url must be set
at org.springframework.util.Assert.hasText(Assert.java:289) ~[spring-core-5.3.22.jar:5.3.22]
at org.flowable.ui.common.properties.FlowableCommonAppProperties.determineIdmAppUrl(FlowableCommonAppProperties.java:150) ~[flowable-ui-common-6.7.2.jar:6.7.2]
at org.flowable.ui.common.service.idm.RemoteIdmServiceImpl.<init>(RemoteIdmServiceImpl.java:60) ~[flowable-ui-common-6.7.2.jar:6.7.2]
at org.flowable.ui.common.security.FlowableUiSecurityAutoConfiguration$RemoteIdmConfiguration.remoteIdmService(FlowableUiSecurityAutoConfiguration.java:120) ~[flowable-ui-common-6.7.2.jar:6.7.2]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.22.jar:5.3.22]
... 20 common frames omitted

解决办法

flowable:
#该配置只是防止报错,没有实际意义
  common:
    app:
      idm-admin:
        password: test
        user: test
        #没有实际意义
      idm-url: http://localhost:8080/flowable-demo

2.3 集成前端ui

将flowable源码的UI放到自己项目resources目录下, 创建static目录
源码下载地址: https://github.com/flowable/flowable-engine/tree/flowable-6.7.2
将以下路径的代码复制到自己工程
/flowable-6.7.2/modules/flowable-ui/flowable-ui-modeler-frontend/src/main/resources/static/modeler
如图

图片.png

打开地址, 效果 http://localhost:8080/modeler/#/processes

图片.png

2.4 如果遇到需要登录情况, 绕过校验

package com.example.springbootflowabledemo.config;

import org.flowable.ui.common.security.SecurityConstants;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * 绕过flowable的登录验证
 */
@Configuration
public class SecurityConfiguration {
    @Configuration(proxyBeanMethods = false)
    //Order配置说明
    // 这个地方相同会报错
    //这个地方如果大于则该配置在FlowableUiSecurityAutoConfiguratio中对应项后加载,不能起到绕过授权作用
    //所以这个地方-1让该配置项在FlowableUiSecurityAutoConfiguratio中对应配置项前加载,以跳过授权
    @Order(SecurityConstants.FORM_LOGIN_SECURITY_ORDER - 1)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.headers().frameOptions().disable();


            http
                    //必须要将csrf设置为disable,不然后面发送POST请求时会报403错误
                    .csrf().disable()
                    //为了简单起见,简单粗暴方式直接放行modeler下面所有请求
                    .authorizeRequests().antMatchers("/modeler/**").permitAll();
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容