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:
#數(shù)據(jù)庫鏈接配置
  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:
#異步執(zhí)行
  async-executor-activate: true
#自動更新數(shù)據(jù)庫
  database-schema-update: true
#校驗流程文件,默認校驗resources下的processes文件夾里的流程文件
  process-definition-location-prefix: classpath*:/processes/
  process-definition-location-suffixes: "**.bpmn20.xml, **.bpmn"

1.3 第一次啟動創(chuàng)建表

圖片.png

1.4 創(chuàng)建的服務端的表

圖片.png

1.5 主要幾張表介紹

  • ACT_RU_TASK 每次啟動的流程都會再這張表中,表示代辦項, 流程結(jié)束會刪除該流程數(shù)據(jù)
  • ACT_RU_EXECUTION 流程執(zhí)行過程表, 會存該流程正在執(zhí)行的過程數(shù)據(jù), 流程結(jié)束會刪除該流程數(shù)據(jù)
  • ACT_RU_VARIABLE 流程變量表, 流程中傳的參數(shù)都會再該表存儲, 流程結(jié)束會刪除該流程數(shù)據(jù)
  • ACT_HI_PROCINST 歷史運行流程, 當流程處理完了, 在ACT_RU_* 表中就不會有數(shù)據(jù), 可以在該表中查詢歷史
  • ACT_HI_TASKINST 歷史運行的task信息,
  • ACT_RE_PROCDEF 流程模板記錄,同一個key多次發(fā)布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={}, 下次執(zhí)行task={}", processInstance.getId(), task.getId());
        }
    }

1.8處理節(jié)點

  • 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 "節(jié)點處理完成!";
    }
  • 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目錄下, 創(chuàng)建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中對應項后加載,不能起到繞過授權(quán)作用
    //所以這個地方-1讓該配置項在FlowableUiSecurityAutoConfiguratio中對應配置項前加載,以跳過授權(quán)
    @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設(shè)置為disable,不然后面發(fā)送POST請求時會報403錯誤
                    .csrf().disable()
                    //為了簡單起見,簡單粗暴方式直接放行modeler下面所有請求
                    .authorizeRequests().antMatchers("/modeler/**").permitAll();
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容