您的位置:首页 > 编程语言 > Java开发

Flowable 快速入门教程:SpringBoot 集成 Flowable + Flowable Modeler 流程配置可视化(超详细)

2019-11-01 20:02 417 查看

Flowable 快速入门教程:SpringBoot 集成 Flowable + Flowable Modeler 流程配置可视化(超详细)

  • 集成 Flowable Modeler
  • 代码修改
  • 访问页面
  • 关闭数据库自动更新
  • 自身 XML 扫描不到的问题
  • 结尾
  • 版本

    这里选择的版本为 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("836369078@qq.com")
    // 设置发件人用户名
    .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("admin@flowable.com");
    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("admin@flowable.org");
    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.json
    stencilset/stencilset_cmmn.json

    启动器修改

    主要修改三个

    1. 引入
      自己目录
      下的 ApplicationConfigurationAppDispatcherServletConfiguration,可参考 app 的启动器
    2. 引入
      Jar 包
      里的 DatabaseConfiguration,这个文件是对表进行更新的,由于
      conf
      目录不引入,因此我们只能单独引入,具体内容可以自己看下这个文件
    3. 移除 Security 自动配置 Spring Cloud 为 Finchley 版本:
      @SpringBootApplication(exclude={SecurityAutoConfiguration.class})
    4. Spring Cloud 为 Greenwich 版本:
      @SpringBootApplication(exclude={SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, SecurityFilterAutoConfiguration.class})
    //启用全局异常拦截器
    @Import(value={
    // 引入修改的配置
    ApplicationConfiguration.class,
    AppDispatcherServletConfiguration.class,
    // 引入 DatabaseConfiguration 表更新转换
    DatabaseConfiguration.class})
    // Eureka 客户端
    @EnableDiscoveryClient
    @ComponentScan(basePackages = {"com.springcloud.*"})
    @MapperScan("com.springcloud.*.dao")
    // 移除 Security 自动配置
    // Spring Cloud 为 Finchley 版本
    // @SpringBootApplication(exclude={SecurityAutoConfiguration.class})
    // Spring Cloud 为 Greenwich 版本
    @SpringBootApplication(exclude={SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, SecurityFilterAutoConfiguration.class})
    public class FlowableApplication {
    public static void main(String[] args) {
    SpringApplication.run(FlowableApplication.class, args);
    }
    }

    访问页面

    https://localhost:8087/

    自动跳转

    关闭数据库自动更新


    创建完数据库后,关闭自动更新。原因是更新的标准并非是你引入的流程引擎的版本,而是官方发布的版本,所以如果一直开启,以后重启之类的可能导致提示版本升级失败,毕竟你的依赖版本并没有升级。

    Factory method 'initProcessEngine' threw exception; nested exception is
    org.flowable.common.engine.api.FlowableException:
    Could not update Flowable database schema: unknown version from database: '6.5.0.1'

    因此除非你确实要提高你的引擎版本到最新,否则不要开启

    假如你出现了上述问题,可尝试:
    1.删掉所有表重建
    这样会创建你当前版本的数据库,这种肯定可以,但是基本上数据是没了,除非你有耐心迁移下。

    2.直接修改当前数据库版本
    就是这张

    ACT_GE_PROPERTY
    的数据,如果出问题了,这里的版本就会变成更新的版本,如:6.5.0.1,状态从创建变为更新,手动直接修正所有参数。本人没尝试过这种方式,应该可行。

    自身 XML 扫描不到的问题

    首页不建议将业务代码和流程引擎混在一个项目中

    如果一定要这样,遇到自己的 XML 总扫描不到,转下面的文章

    SpringBoot 集成 Flowable + Flowable Modeler 导致自身 XML 扫描不到解决方案

    结尾

    文章如果存在什么问题,请及时留言反馈

    集成后的代码:https://gitee.com/linjinp-spring-cloud/linjinp-spring-cloud
    代码在

    flowable-demo
    包,IDEA
    Active profiles
    配置为
    sit
    测试分支,单独启动即可

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐