0


SpringBoot 集成Flowable设计器(Flowable-ui)

一、项目场景:

提示:使用版本6.7.0

公司使用前后端项目分离,前端使用bpmn插件生成bpmn xml文件,后端解析处理数据。今天主要介绍后端集成flowable设计器的过程中遇到的问题。
如需了解flowable框架集成请参考文档
Flowable BPMN 用户手册 (v 6.3.0)


二、集成过程

提示:项目中遇到的问题:

为什么需要自己集成Flowable设计器?因为SpringBoot提供的依赖只集成Flowable引擎模块,没有集成modeler模块。SpringBoot集成Flowable需要导入如下依赖:

<!-- flowable --><dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter-process</artifactId><version>${flowable.version}</version></dependency>


可以看到没有集成和modeler相关的依赖,如下是flowable源码中提供的流程设计器模块:
flowable-ui-modeler-conf: 放置一些列的配置项
flowable-ui-modeler-frontend: 前端
flowable-ui-modeler-logic: 放置Service以及dao层
flowable-ui-modeler-rest: 放置Controller层
因为只需要集成flowable操作model 接口相关组件,所以只需要集成logic模块即可,添加依赖如下:

<!-- 配置ui集成 --><dependency><groupId>org.flowable</groupId><artifactId>flowable-ui-modeler-logic</artifactId><version>${flowable.version}</version></dependency>

三、问题总结:

提示:这里填写问题的分析:

1、程序启动报错(flowable.common.app.idm-url must be set)

`Failedtoinstantiate[org.flowable.ui.common.service.idm.RemoteIdmService]:Factory method 'remoteIdmService' threw exception; nested exception is java.lang.IllegalArgumentException: `flowable.common.app.idm-url` must be set`

这个是由于flowable调用自己的用户权限导致的,如果把flowable集成自己的框架里面,就不需要用它自带的用户体现和权限了。

解决方案:将FlowableUiSecurityAutoConfiguration排除

@SpringBootApplication(exclude ={FlowableUiSecurityAutoConfiguration.class})

2、引入modelService报红,运行报错

Field modelService in com.nmb.zx.base.sys.flow.service.FlowModelInfoService required a bean of type 'org.flowable.ui.modeler.serviceapi.ModelService' that could not be found.

解决方案:参考flowable flowable-ui-modeler-conf组件中的源码中的配置类扫描我们需要的注入的类所在的包即可:
添加ModelerBeanConfig.java配置类到项目任意位置:

importorg.flowable.ui.common.properties.FlowableCommonAppProperties;importorg.flowable.ui.modeler.repository.ModelRepositoryImpl;importorg.flowable.ui.modeler.service.FlowableModelQueryService;importorg.flowable.ui.modeler.service.ModelImageService;importorg.flowable.ui.modeler.service.ModelServiceImpl;importorg.flowable.ui.modeler.serviceapi.ModelService;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.FilterType;/**
 * Greated by xiang on 2023/2/27
 */@Configuration@ComponentScan(value ={//       "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 ={@ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE, value =ModelRepositoryImpl.class)})@EnableConfigurationProperties({FlowableCommonAppProperties.class})publicclassModelerBeanConfig{@BeanpublicModelServicecreateModelService(){returnnewModelServiceImpl();}@BeanpublicModelImageServicecreateModelImageService(){returnnewModelImageService();}@BeanpublicFlowableModelQueryServicecreateFlowableModelQueryService(){returnnewFlowableModelQueryService();}}

mybatisPlus中添加配置
在这里插入图片描述添加BPMN配置文件FlowBpmnConfig

importcom.fasterxml.jackson.databind.ObjectMapper;importcom.nmb.zx.base.core.config.flow.customcache.CustomDeploymentCache;importcom.nmb.zx.base.core.config.flow.customcache.CustomProcessDefinitionInfoCache;importorg.apache.ibatis.session.SqlSessionFactory;importorg.flowable.bpmn.converter.BpmnXMLConverter;importorg.flowable.spring.SpringProcessEngineConfiguration;importorg.flowable.spring.boot.EngineConfigurationConfigurer;importorg.flowable.validation.ProcessValidatorFactory;importorg.mybatis.spring.SqlSessionTemplate;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.support.PropertySourcesPlaceholderConfigurer;/**
 * 功能描述: <br>
 * 〈flowable配置〉
 * @Author: 85122
 * @Date: 2023/2/28 15:16
 */@ConfigurationpublicclassFlowBpmnConfigimplementsEngineConfigurationConfigurer<SpringProcessEngineConfiguration>{@AutowiredprivateCustomDeploymentCache customDeploymentCache;@AutowiredprivateCustomProcessDefinitionInfoCache customProcessDefinitionInfoCache;@Overridepublicvoidconfigure(SpringProcessEngineConfiguration configuration){
        configuration.setEnableProcessDefinitionInfoCache(true);
        configuration.setProcessDefinitionCache(customDeploymentCache);
        configuration.setProcessDefinitionInfoCache(customProcessDefinitionInfoCache);//设置自定义的uuid生成策略
        configuration.setIdGenerator(uuidGenerator());}@BeanpublicProcessValidatorFactoryprocessValidator(){returnnewProcessValidatorFactory();}@BeanpublicObjectMapperobjectMapper(){returnnewObjectMapper();}@BeanpublicUuidGeneratoruuidGenerator(){returnnewUuidGenerator();}/**
     * BpmnXMLConverter
     *
     * @return BpmnXMLConverter
     */@BeanpublicBpmnXMLConvertercreateBpmnXMLConverter(){returnnewBpmnXMLConverter();}/**
     * 在配置文件中如果没有字段,使用@Value的时候就会忽略掉,不会报错
     *
     * @return
     */@BeanpublicstaticPropertySourcesPlaceholderConfigurerplaceholderConfigurer(){PropertySourcesPlaceholderConfigurer configurer =newPropertySourcesPlaceholderConfigurer();
        configurer.setIgnoreUnresolvablePlaceholders(true);return configurer;}@Bean(destroyMethod ="clearCache")@Qualifier("flowableModeler")publicSqlSessionTemplatemodelerSqlSessionTemplate(SqlSessionFactory sqlSessionFactory){returnnewSqlSessionTemplate(sqlSessionFactory);}}
importorg.flowable.common.engine.impl.persistence.StrongUuidGenerator;/**
 * 功能描述: <br>
 * 〈uuid生成规则〉
 * @Author: 85122
 * @Date: 2023/2/28 15:16
 */publicclassUuidGeneratorextendsStrongUuidGenerator{@OverridepublicStringgetNextId(){String uuid =super.getNextId();
        uuid = uuid.replaceAll("-","");return uuid;}}
importorg.flowable.common.engine.impl.persistence.deploy.DeploymentCache;importorg.flowable.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry;importorg.flowable.engine.repository.ProcessDefinition;importorg.springframework.stereotype.Component;importjava.util.ArrayList;importjava.util.Collection;importjava.util.Collections;/**
 * Very simplistic cache implementation that only caches one process definition.
 * 
 * @author Joram Barrez
 */@ComponentpublicclassCustomDeploymentCacheimplementsDeploymentCache<ProcessDefinitionCacheEntry>{protectedString id;protectedProcessDefinitionCacheEntry entry;@OverridepublicProcessDefinitionCacheEntryget(String id){if(id.equals(this.id)){return entry;}returnnull;}@Overridepublicvoidadd(String id,ProcessDefinitionCacheEntry object){this.id = id;this.entry = object;}@Overridepublicvoidremove(String id){if(id.equals(this.id)){this.id =null;this.entry =null;}}@Overridepublicvoidclear(){this.id =null;this.entry =null;}@Overridepublicbooleancontains(String id){return id.equals(this.id);}@OverridepublicCollection<ProcessDefinitionCacheEntry>getAll(){if(entry !=null){returnCollections.singletonList(entry);}else{returnnewArrayList<>();}}@Overridepublicintsize(){if(entry !=null){return1;}else{return0;}}// For testing purposes onlypublicProcessDefinitiongetCachedProcessDefinition(){if(entry ==null){returnnull;}return entry.getProcessDefinition();}}
importorg.flowable.common.engine.impl.persistence.deploy.DeploymentCache;importorg.flowable.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;importorg.springframework.stereotype.Component;importjava.util.Collection;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;@ComponentpublicclassCustomProcessDefinitionInfoCacheimplementsDeploymentCache<ProcessDefinitionInfoCacheObject>{privatefinalMap<String,ProcessDefinitionInfoCacheObject> cache =newConcurrentHashMap<>();@OverridepublicProcessDefinitionInfoCacheObjectget(String id){return cache.get(id);}@Overridepublicbooleancontains(String id){return cache.containsKey(id);}@Overridepublicvoidadd(String id,ProcessDefinitionInfoCacheObject object){
        cache.put(id, object);}@Overridepublicvoidremove(String id){
        cache.remove(id);}@Overridepublicvoidclear(){
        cache.clear();}@OverridepublicCollection<ProcessDefinitionInfoCacheObject>getAll(){return cache.values();}@Overridepublicintsize(){return cache.size();}}

3、启动后访问接口直接重定向到登录页面

在这里插入图片描述

importorg.flowable.ui.common.security.SecurityConstants;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.annotation.Order;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;/**
 * 说明:重构ModelerSecurity 绕过登录
 */@Configuration(proxyBeanMethods =false)@EnableWebSecuritypublicclassModelerSecurityConfiguration{@Configuration@Order(SecurityConstants.MODELER_API_SECURITY_ORDER)publicstaticclassModelerApiWebSecurityConfigurationAdapterextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{SavedRequestAwareAuthenticationSuccessHandler successHandler =newSavedRequestAwareAuthenticationSuccessHandler();
            successHandler.setTargetUrlParameter("redirectTo");
            http.headers().frameOptions().disable();
            http.csrf().disable().authorizeRequests().antMatchers("/**/**").permitAll().anyRequest().authenticated().and().httpBasic();}}}

4、运行成功请求接口

找不到act_de_model表,因为flowable将act_re_model改成了act_de_model表了,所以需要手动添加配置类生产act_de_model表:

importliquibase.Liquibase;importliquibase.database.Database;importliquibase.database.DatabaseConnection;importliquibase.database.DatabaseFactory;importliquibase.database.jvm.JdbcConnection;importliquibase.exception.DatabaseException;importliquibase.resource.ClassLoaderResourceAccessor;importorg.flowable.ui.common.service.exception.InternalServerErrorException;importorg.slf4j.LoggerFactory;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjavax.sql.DataSource;/**
 * 功能描述: <br>
 * 〈生成ACT_DE_开头的数据表〉
 * @Param:  * @param null
 * @Return:
 * @Author: 85122
 * @Date: 2023/2/28 15:00
 */@ConfigurationpublicclassDatabaseConfiguration{privatestaticfinalorg.slf4j.LoggerLOGGER=LoggerFactory.getLogger(DatabaseConfiguration.class);protectedstaticfinalStringLIQUIBASE_CHANGELOG_PREFIX="ACT_DE_";@BeanpublicLiquibaseliquibase(DataSource dataSource){LOGGER.info("Configuring Liquibase");Liquibase liquibase =null;try{DatabaseConnection connection =newJdbcConnection(dataSource.getConnection());Database database =DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);
            database.setDatabaseChangeLogTableName(LIQUIBASE_CHANGELOG_PREFIX+ database.getDatabaseChangeLogTableName());
            database.setDatabaseChangeLogLockTableName(LIQUIBASE_CHANGELOG_PREFIX+ database.getDatabaseChangeLogLockTableName());
            liquibase =newLiquibase("META-INF/liquibase/flowable-modeler-app-db-changelog.xml",newClassLoaderResourceAccessor(), database);
            liquibase.update("flowable");return liquibase;}catch(Exception e){thrownewInternalServerErrorException("Error creating liquibase database", e);}finally{closeDatabase(liquibase);}}privatevoidcloseDatabase(Liquibase liquibase){if(liquibase !=null){Database database = liquibase.getDatabase();if(database !=null){try{
                    database.close();}catch(DatabaseException e){LOGGER.warn("Error closing database", e);}}}}}

标签: spring boot ui java

本文转载自: https://blog.csdn.net/weixin_37304961/article/details/129255799
版权归原作者 我的瓦洛佳 所有, 如有侵权,请联系我们删除。

“SpringBoot 集成Flowable设计器(Flowable-ui)”的评论:

还没有评论