Flowable 快速入門教程:SpringBoot 集成 Flowable + Flowable Modeler 流程配置可視化(超詳細)

版本

這裏選擇的版本爲 6.4.1

Flowable 6.4.1 release

中文版用戶手冊:Flowable BPMN 用戶手冊

如果需要集成 Flowable Modeler 的請下載源碼

PS:不要選擇 6.4.2 版本,這個版本有發版問題

加依賴

由於是 spring-boot 集成,因此直接選擇 flowable-spring-boot-starter,裏面提供了齊全的 REST API

<!-- Flowable spring-boot 版套餐 -->
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.4.1</version>
</dependency>

其他的也可以直接選擇 flowable-engine

<!-- flowable-engine -->
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-engine</artifactId>
    <version>6.4.1</version>
</dependency>

加配置

# flowable 配置
flowable:
  # 關閉異步,不關閉歷史數據的插入就是異步的,會在同一個事物裏面,無法回滾
  # 開發可開啓會提高些效率,上線需要關閉
  async-executor-activate: false

內部日誌

Flowable 使用 SLF4J 作爲內部日誌框架。在這個例子中,我們使用 log4j 作爲 SLF4J 的實現。

加依賴

<!-- Flowable 內部日誌採用 SLF4J -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>

resource 目錄下新建文件 log4j.properties

log4j.rootLogger=DEBUG, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

初始化 ProcessEngine

代碼初始化

// 流程引擎配置
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                    .setJdbcUrl(url)
                    .setJdbcUsername(username)
                    .setJdbcPassword(password)
                    .setJdbcDriver(driverClassName)
                    // 初始化基礎表,不需要的可以改爲 DB_SCHEMA_UPDATE_FALSE
                    .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 初始化流程引擎對象
ProcessEngine processEngine = cfg.buildProcessEngine();

flowable.cfg.xml 初始化

代碼部分

// 流程引擎配置
ProcessEngineConfiguration cfg = ProcessEngineConfiguration
	// 根據文件名獲取配置文件
        //.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
        // 獲取默認配置文件,默認的就是 activiti.cfg.xml
        .createProcessEngineConfigurationFromResourceDefault()
        // 初始化基礎表,不需要的可以改爲 DB_SCHEMA_UPDATE_FALSE
        .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 初始化流程引擎對象
ProcessEngine processEngine = cfg.buildProcessEngine();

新建 flowable.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/test"/>
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUsername" value="root"/>
        <property name="jdbcPassword" value="123456"/>
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>

我的初始化示例

我的配置文件 ProcessEngineConfig.java

依賴

  • spring-boot-configuration-processor 加載配置文件
  • lomok 簡化 java 代碼
<!-- 配置文件處理器 -->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
 </dependency>
 <!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.0</version>
    <scope>provided</scope>
</dependency>
/**
 * 流程引擎配置文件
 * @author: linjinp
 * @create: 2019-10-21 16:49
 **/
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
@Data
public class ProcessEngineConfig {

    private Logger logger = LoggerFactory.getLogger(ProcessEngineConfig.class);

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.publicKey}")
    private String publicKey;

    /**
     * 初始化流程引擎
     * @return
     */
    @Primary
    @Bean(name = "processEngine")
    public ProcessEngine initProcessEngine() {
        logger.info("=============================ProcessEngineBegin=============================");

        // 流程引擎配置
        ProcessEngineConfiguration cfg = null;

        try {
            cfg = new StandaloneProcessEngineConfiguration()
                    .setJdbcUrl(url)
                    .setJdbcUsername(username)
                    .setJdbcPassword(ConfigTools.decrypt(publicKey, password))
                    .setJdbcDriver(driverClassName)
                    // 初始化基礎表,不需要的可以改爲 DB_SCHEMA_UPDATE_FALSE
                    .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
                    // 默認郵箱配置
                    // 發郵件的主機地址,先用 QQ 郵箱
                    .setMailServerHost("smtp.qq.com")
                    // POP3/SMTP服務的授權碼
                    .setMailServerPassword("xxxxxxx")
                    // 默認發件人
                    .setMailServerDefaultFrom("[email protected]")
                    // 設置發件人用戶名
                    .setMailServerUsername("管理員")
                    // 解決流程圖亂碼
                    .setActivityFontName("宋體")
                    .setLabelFontName("宋體")
                    .setAnnotationFontName("宋體");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 初始化流程引擎對象
        ProcessEngine processEngine = cfg.buildProcessEngine();
        logger.info("=============================ProcessEngineEnd=============================");
        return processEngine;
    }
}

PS:這裏沒有單獨對流程引擎中的 8 個核心服務做初始化,是因爲使用 flowable-spring-boot-starter 依賴,會自動幫忙註冊好,不需要自己再註冊,直接使用即可

如果你使用的依賴是 flowable-engine,你可能還需要

//八大接口
// 業務流程的定義相關服務
@Bean
public RepositoryService repositoryService(ProcessEngine processEngine){
    return processEngine.getRepositoryService();
}

// 流程對象實例相關服務
@Bean
public RuntimeService runtimeService(ProcessEngine processEngine){
    return processEngine.getRuntimeService();
}

// 流程任務節點相關服務
@Bean
public TaskService taskService(ProcessEngine processEngine){
    return processEngine.getTaskService();
}

// 流程歷史信息相關服務
@Bean
public HistoryService historyService(ProcessEngine processEngine){
    return processEngine.getHistoryService();
}

// 表單引擎相關服務
@Bean
public FormService formService(ProcessEngine processEngine){
    return processEngine.getFormService();
}

// 用戶以及組管理相關服務
@Bean
public IdentityService identityService(ProcessEngine processEngine){
    return processEngine.getIdentityService();
}

// 管理和維護相關服務
@Bean
public ManagementService managementService(ProcessEngine processEngine){
    return processEngine.getManagementService();
}

// 動態流程服務
@Bean
public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine){
    return processEngine.getDynamicBpmnService();
}
//八大接口 end

集成 Flowable Modeler

下載源碼

版本爲 6.4.1,不多說了,看文章開頭下載源碼

文件位置

打開文件夾 flowable-ui-modeler

路徑:flowable-engine-flowable-6.4.1\modules\flowable-ui-modeler

  • flowable-ui-modeler-app:主要爲前端界面,文件在 resource/static
  • flowable-ui-modeler-conf:主要爲一些配置文件 Configuration
  • flowable-ui-modeler-logic:主要爲一些業務邏輯還有 SQL
  • flowable-ui-modeler-rest:主要爲 rest 接口

這些都是需要用到的

新增依賴

使用 rest,logic,conf 的依賴

<!-- flowable 集成依賴 rest,logic,conf -->
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-ui-modeler-rest</artifactId>
    <version>6.4.1</version>
</dependency>
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-ui-modeler-logic</artifactId>
    <version>6.4.1</version>
</dependency>
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-ui-modeler-conf</artifactId>
    <version>6.4.1</version>
</dependency>

代碼集成

前端代碼集成

在項目中的 resource 文件夾下新建一個 static 文件夾

SpringBoot 能自動讀取 static 目錄下的靜態文件,因此文件夾名稱不可隨意更改

複製 flowable-ui-modeler-app 包中 resources\static 下所有文件,複製到新建的 static

路徑:flowable-engine-flowable-6.4.1\modules\flowable-ui-modeler\flowable-ui-modeler-app\src\main\resources\static

在這裏插入圖片描述

後端代碼集成

複製以下文件到自己的項目中

ApplicationConfiguration.java

路徑:flowable-engine-flowable-6.4.1\modules\flowable-ui-modeler\flowable-ui-modeler-conf\src\main\java\org\flowable\ui\modeler\conf

原因:這個文件是啓動中必要的配置文件,需要做修改,詳細的可以看下 app 中啓動類,文件路徑隨意

AppDispatcherServletConfiguration.java

路徑:flowable-engine-flowable-6.4.1\modules\flowable-ui-modeler\flowable-ui-modeler-conf\src\main\java\org\flowable\ui\modeler\servlet

原因:這個文件是啓動中必要的配置文件,需要做修改,詳細的可以看下 app 中啓動類,文件路徑隨意

StencilSetResource.java

路徑:flowable-engine-flowable-6.4.1\modules\flowable-ui-modeler\flowable-ui-modeler-rest\src\main\java\org\flowable\ui\modeler\rest\app

同時在 resource 下新建一個 stencilset 文件夾用來放漢化文件,可以直接下載我上傳的

原因:國際化配置加載,爲了使用我們自己的漢化文件因此把文件拿出來並修改,文件路徑隨意

PS:複製出來後要對這個文件進行重命名,否則會與 Jar 包裏的文件產生 Bean 存在的衝突

我這重命名後叫 FlowableStencilSetResource.java

SecurityUtils

路徑:flowable-engine-flowable-6.4.1\modules\flowable-ui-common\src\main\java\org\flowable\ui\common\security

原因:流程模型加載需要調用的工具類,文件路徑需要與原路徑保持一致

也就是包路徑必須是 org.flowable.ui.common.security 這樣在 Jar 中的方法在調用時會覆蓋原 Jar 裏的工具類

結構

在這裏插入圖片描述

代碼修改

ApplicationConfiguration 修改

此文件不需要過多說明,主要移除 IDM 方面的配置

注意 conf 目錄不要引入,裏面也包含和 IDM 相關的配置

@Configuration
@EnableConfigurationProperties(FlowableModelerAppProperties.class)
@ComponentScan(basePackages = {
//        "org.flowable.ui.modeler.conf", // 不引入 conf
        "org.flowable.ui.modeler.repository",
        "org.flowable.ui.modeler.service",
//        "org.flowable.ui.modeler.security", //授權方面的都不需要
//        "org.flowable.ui.common.conf", // flowable 開發環境內置的數據庫連接
//        "org.flowable.ui.common.filter", // IDM 方面的過濾器
        "org.flowable.ui.common.service",
        "org.flowable.ui.common.repository",
        //
//        "org.flowable.ui.common.security",//授權方面的都不需要
        "org.flowable.ui.common.tenant" },excludeFilters = {
        // 移除 RemoteIdmService
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = RemoteIdmService.class)
    }
)
public class ApplicationConfiguration {

    @Bean
    public ServletRegistrationBean modelerApiServlet(ApplicationContext applicationContext) {
        AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext();
        dispatcherServletConfiguration.setParent(applicationContext);
        dispatcherServletConfiguration.register(ApiDispatcherServletConfiguration.class);
        DispatcherServlet servlet = new DispatcherServlet(dispatcherServletConfiguration);
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(servlet, "/api/*");
        registrationBean.setName("Flowable Modeler App API Servlet");
        registrationBean.setLoadOnStartup(1);
        registrationBean.setAsyncSupported(true);
        return registrationBean;
    }
}

AppDispatcherServletConfiguration 修改

同理,爲了不引入 IDM 的配置

@Configuration
@ComponentScan(value = { "org.flowable.ui.modeler.rest.app",
        // 不加載 rest,因爲 getAccount 接口需要我們自己實現
//        "org.flowable.ui.common.rest"
    },excludeFilters = {
        // 移除 EditorUsersResource 與 EditorGroupsResource,因爲不使用 IDM 部分
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorUsersResource.class),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = EditorGroupsResource.class),
        // 配置文件用自己的
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StencilSetResource.class),
    }
)
@EnableAsync
public class AppDispatcherServletConfiguration implements WebMvcRegistrations {

    private static final Logger LOGGER = LoggerFactory.getLogger(AppDispatcherServletConfiguration.class);

    @Bean
    public SessionLocaleResolver localeResolver() {
        return new SessionLocaleResolver();
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LOGGER.debug("Configuring localeChangeInterceptor");
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("language");
        return localeChangeInterceptor;
    }

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        LOGGER.debug("Creating requestMappingHandlerMapping");
        RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
        requestMappingHandlerMapping.setRemoveSemicolonContent(false);
        Object[] interceptors = { localeChangeInterceptor() };
        requestMappingHandlerMapping.setInterceptors(interceptors);
        return requestMappingHandlerMapping;
    }
}

SecurityUtils 修改

這個主要保存時候會調這裏的接口

getCurrentUserObject 方法進行修改,讓他獲取默認的 admin

/**
 * @return the {@link User} object associated with the current logged in user.
 */
public static User getCurrentUserObject() {
    if (assumeUser != null) {
        return assumeUser;
    }

    RemoteUser user = new RemoteUser();
    user.setId("admin");
    user.setDisplayName("Administrator");
    user.setFirstName("Administrator");
    user.setLastName("Administrator");
    user.setEmail("[email protected]");
    user.setPassword("123456");
    List<String> pris = new ArrayList<>();
    pris.add(DefaultPrivileges.ACCESS_MODELER);
    pris.add(DefaultPrivileges.ACCESS_IDM);
    pris.add(DefaultPrivileges.ACCESS_ADMIN);
    pris.add(DefaultPrivileges.ACCESS_TASK);
    pris.add(DefaultPrivileges.ACCESS_REST_API);
    user.setPrivileges(pris);
    return user;
}

新增 getAccount 接口

新建文件 FlowableController,自己隨意

在加載頁面時候會調用這個接口獲取用戶信息,由於我們繞過了登陸,因此給個默認的用戶 admin

爲了不和原文件衝突,所以 @RequestMapping("/login")

/**
 * Flowable 相關接口
 * @author linjinp
 * @date 2019/10/31 10:55
 */
@RestController
@RequestMapping("/login")
public class FlowableController {

    /**
     * 獲取默認的管理員信息
     * @return
     */
    @RequestMapping(value = "/rest/account", method = RequestMethod.GET, produces = "application/json")
    public UserRepresentation getAccount() {
        UserRepresentation userRepresentation = new UserRepresentation();
        userRepresentation.setId("admin");
        userRepresentation.setEmail("[email protected]");
        userRepresentation.setFullName("Administrator");
//        userRepresentation.setLastName("Administrator");
        userRepresentation.setFirstName("Administrator");
        List<String> privileges = new ArrayList<>();
        privileges.add(DefaultPrivileges.ACCESS_MODELER);
        privileges.add(DefaultPrivileges.ACCESS_IDM);
        privileges.add(DefaultPrivileges.ACCESS_ADMIN);
        privileges.add(DefaultPrivileges.ACCESS_TASK);
        privileges.add(DefaultPrivileges.ACCESS_REST_API);
        userRepresentation.setPrivileges(privileges);
        return userRepresentation;
    }
}

url-config.js 修改

路徑:resource\static\scripts\configuration\url-conf.js

getAccountUrl 的路徑改爲上面自己的 getAccount 接口的路徑
在這裏插入圖片描述

StencilSetResource漢化

記得重命名,我這重命名後叫 FlowableStencilSetResource

把配置文件路徑改爲我們自己目錄下的路徑

stencilset/stencilset_bpmn.jsonstencilset/stencilset_cmmn.json

在這裏插入圖片描述

啓動器修改

主要修改三個

  1. 引入 自己目錄 下的 ApplicationConfigurationAppDispatcherServletConfiguration,可參考 app 的啓動器
  2. 引入 Jar 包 裏的 DatabaseConfiguration,這個文件是對錶進行更新的,由於 conf 目錄不引入,因此我們只能單獨引入,具體內容可以自己看下這個文件
  3. 移除 Security 自動配置 exclude={SecurityAutoConfiguration.class}
//啓用全局異常攔截器
@Import(value={
        // 引入修改的配置
        ApplicationConfiguration.class,
        AppDispatcherServletConfiguration.class,
        // 引入 DatabaseConfiguration 表更新轉換
        DatabaseConfiguration.class})
// Eureka 客戶端
@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.springcloud.*"})
@MapperScan("com.springcloud.*.dao")
// 移除 Security 自動配置
@SpringBootApplication(exclude={SecurityAutoConfiguration.class})
public class FlowableApplication {
    public static void main(String[] args) {
        SpringApplication.run(FlowableApplication.class, args);
    }
}

訪問頁面

https://localhost:8087/

自動跳轉

在這裏插入圖片描述

自身 XML 掃描不到的問題

首頁不建議將業務代碼和流程引擎混在一個項目中

如果一定要這樣,遇到自己的 XML 總掃描不到,轉下面的文章

SpringBoot 集成 Flowable + Flowable Modeler 導致自身 XML 掃描不到解決方案

結尾

文章如果存在什麼問題,請及時留言反饋

集成後的代碼:https://gitee.com/linjinp-spring-cloud/linjinp-spring-cloud
代碼在 flowable-demo 包,IDEA Active profiles 配置爲 sit 測試分支,單獨啓動即可

發佈了103 篇原創文章 · 獲贊 387 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章