Ruoyi 整合Flowable UI Modeler 6.7.2
一、Spring Boot整合Flowable UI Modeler 6.7.2在若依项目中创建基础模块,按照Spring Boot整合Flowable UI Modeler 6.7.2,可以参考上一篇文章,文章地址如下:Spring Boot 整合 Flowable-ui-modeler 6.7.2_wangdaoyin2010的博客-CSDN博客二、修改数据库配置按照Spring Boot方式
一、Spring Boot整合Flowable UI Modeler 6.7.2
在若依项目中创建基础模块,按照Spring Boot整合Flowable UI Modeler 6.7.2,可以参考上一篇文章,文章地址如下:
Spring Boot 整合 Flowable-ui-modeler 6.7.2_wangdaoyin2010的博客-CSDN博客
二、修改数据库配置
按照Spring Boot方式整合Modeler后,在flowable-ui-modeler-conf依赖中类ModelerDatabaseConfiguration中注入了SqlSessionFactory和SqlSessionTemplate数据库相关Bean。这些注入的Bean会与ruoyi中的MyBatis自动注入的会冲突。所以需要需要重写flowable-ui-modeler-conf中的ModelerDatabaseConfiguration类中对应响应的配置进行重写。
1、覆盖ModelerDatabaseConfiguration
床建ModelerDatabaseConfiguration类,覆盖flowable-ui-modeler-conf依赖中的该类。
@Configuration(proxyBeanMethods = false)
public class ModelerDatabaseConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(ModelerDatabaseConfiguration.class);
protected static final String LIQUIBASE_CHANGELOG_PREFIX = "ACT_DE_";
@Autowired
protected FlowableModelerAppProperties modelerAppProperties;
@Autowired
protected MybatisProperties mybatisProperties;
@Autowired
protected ResourceLoader resourceLoader;
protected static Properties databaseTypeMappings = getDefaultDatabaseTypeMappings();
public static final String DATABASE_TYPE_H2 = "h2";
public static final String DATABASE_TYPE_HSQL = "hsql";
public static final String DATABASE_TYPE_MYSQL = "mysql";
public static final String DATABASE_TYPE_ORACLE = "oracle";
public static final String DATABASE_TYPE_POSTGRES = "postgres";
public static final String DATABASE_TYPE_MSSQL = "mssql";
public static final String DATABASE_TYPE_DB2 = "db2";
public static Properties getDefaultDatabaseTypeMappings() {
Properties databaseTypeMappings = new Properties();
databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2);
databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL);
databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL);
databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL);
databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE);
databaseTypeMappings.setProperty("PostgreSQL", DATABASE_TYPE_POSTGRES);
databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL);
databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2);
return databaseTypeMappings;
}
@Bean
@Qualifier("flowableModeler")
@Primary
public SqlSessionFactory modelerSqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
String databaseType = initDatabaseType(dataSource);
if (databaseType == null) {
throw new FlowableException("couldn't deduct database type");
}
try {
Properties properties = new Properties();
properties.put("prefix", modelerAppProperties.getDataSourcePrefix());
properties.put("blobType", "BLOB");
properties.put("boolValue", "TRUE");
properties.load(this.getClass().getClassLoader().getResourceAsStream("org/flowable/db/properties/" + databaseType + ".properties"));
sqlSessionFactoryBean.setConfigurationProperties(properties);
//这个是原始代码,只添加flowable的扫描路径
// sqlSessionFactoryBean
// .setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:/META-INF/modeler-mybatis-mappings/*.xml"));
//由于后面要设置该SqlSessionFactory为主要的SqlSessionFactory,
// 然后Ruoyi中使用时Mybatis自动注入,所以在这个地方就需要添加Ruoyi配置扫描
ResourcePatternResolver resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
List<Resource> allResourceList = new ArrayList<>();
List<String> mapperLocations = new ArrayList<>();
//先添加
mapperLocations.add("classpath:/META-INF/modeler-mybatis-mappings/*.xml");
mapperLocations.add("classpath*:/mapper/**/*Mapper.xml");
for (String mapperLocation : mapperLocations) {
try {
Resource[] resources = resourcePatternResolver.getResources(mapperLocation);
allResourceList.addAll(Arrays.asList(resources));
} catch (Exception ex) {
throw new FlowableException("Could not create sqlSessionFactory", ex);
}
}
Resource[] allResourceArr = allResourceList.toArray(new Resource[allResourceList.size()]);
//因为若依中使用了类别名基础包,所以需要在这个地方进行添加
sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackage());
sqlSessionFactoryBean.setMapperLocations(allResourceArr);
sqlSessionFactoryBean.afterPropertiesSet();
return sqlSessionFactoryBean.getObject();
} catch (Exception e) {
throw new FlowableException("Could not create sqlSessionFactory", e);
}
}
@Bean(destroyMethod = "clearCache")
// destroyMethod: see https://github.com/mybatis/old-google-code-issues/issues/778
@Qualifier("flowableModeler")
@Primary
public SqlSessionTemplate modelerSqlSessionTemplate(@Qualifier("flowableModeler") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
@Qualifier("flowableModeler")
public Liquibase modelerLiquibase(DataSource dataSource) {
LOGGER.info("Configuring Liquibase");
try {
return LiquibaseUtil.runInFlowableScope(() -> createAndUpdateLiquibase(dataSource));
} catch (Exception e) {
throw new InternalServerErrorException("Error creating liquibase database", e);
}
}
protected Liquibase createAndUpdateLiquibase(DataSource dataSource) {
Liquibase liquibase = null;
try {
DatabaseConnection connection = new JdbcConnection(dataSource.getConnection());
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);
database.setDatabaseChangeLogTableName(LIQUIBASE_CHANGELOG_PREFIX + database.getDatabaseChangeLogTableName());
database.setDatabaseChangeLogLockTableName(LIQUIBASE_CHANGELOG_PREFIX + database.getDatabaseChangeLogLockTableName());
liquibase = new Liquibase("META-INF/liquibase/flowable-modeler-app-db-changelog.xml", new ClassLoaderResourceAccessor(), database);
liquibase.update("flowable");
return liquibase;
} catch (Exception e) {
throw new InternalServerErrorException("Error creating liquibase database", e);
} finally {
closeDatabase(liquibase);
}
}
protected String initDatabaseType(DataSource dataSource) {
String databaseType = null;
Connection connection = null;
try {
connection = dataSource.getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
String databaseProductName = databaseMetaData.getDatabaseProductName();
LOGGER.info("database product name: '{}'", databaseProductName);
databaseType = databaseTypeMappings.getProperty(databaseProductName);
if (databaseType == null) {
throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'");
}
LOGGER.info("using database type: {}", databaseType);
} catch (SQLException e) {
LOGGER.error("Exception while initializing Database connection", e);
} finally {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
LOGGER.error("Exception while closing the Database connection", e);
}
}
return databaseType;
}
private void closeDatabase(Liquibase liquibase) {
if (liquibase != null) {
Database database = liquibase.getDatabase();
if (database != null) {
try {
database.close();
} catch (DatabaseException e) {
LOGGER.warn("Error closing database", e);
}
}
}
}
}
2、添加注解@Primary
由于flowable-ui-modeler-rest中对SqlSessionTemplate和SqlSessionFactory注入添加了@Qualifier("flowableModeler"),所以不能通过只保留Mybatis自动注入的Bean。所以在这两个Bean注入的地方添加@Primary,让MyBatis自动注入的时候使用这个地方生成的bean,就不会报两个Bean不知道怎么选的错误。
Flowable-logic中对SqlSessionTemplate和SqlSessionFactory的注入代码如下
@Component
public class ModelHistoryRepositoryImpl implements ModelHistoryRepository {
private static final String NAMESPACE = "org.flowable.ui.modeler.domain.ModelHistory.";
@Autowired
@Qualifier("flowableModeler")
protected SqlSessionTemplate sqlSessionTemplate;
}
@Component
public class ModelRelationRepositoryImpl implements ModelRelationRepository {
private static final String NAMESPACE = "org.flowable.ui.modeler.domain.ModelRelation.";
@Autowired
@Qualifier("flowableModeler")
protected SqlSessionTemplate sqlSessionTemplate;
}
@Component
public class ModelRepositoryImpl implements ModelRepository {
private static final String NAMESPACE = "org.flowable.ui.modeler.domain.Model.";
@Autowired
@Qualifier("flowableModeler")
protected SqlSessionTemplate sqlSessionTemplate;
}
3、配置SqlSessionFactory提价ruoyi中mapper扫描
由于使用了该类中创建的SqlSessionFactory,所以需要将ruoyi中的mapper添加到该工厂下进行扫描。ruoyi中Mapper可以参考nacos数据库配置,配置如下
# mybatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.system
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath:mapper/**/*.xml
注意:在添加扫描路径的时候,需要搜索指定包别名
具体修改代码如下
sqlSessionFactoryBean.setConfigurationProperties(properties);
//这个是原始代码,只添加flowable的扫描路径
// sqlSessionFactoryBean
// .setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:/META-INF/modeler-mybatis-mappings/*.xml"));
//由于后面要设置该SqlSessionFactory为主要的SqlSessionFactory,
// 然后Ruoyi中使用时Mybatis自动注入,所以在这个地方就需要添加Ruoyi配置扫描
ResourcePatternResolver resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
List<Resource> allResourceList = new ArrayList<>();
List<String> mapperLocations = new ArrayList<>();
//先添加
mapperLocations.add("classpath:/META-INF/modeler-mybatis-mappings/*.xml");
mapperLocations.add("classpath*:/mapper/**/*Mapper.xml");
for (String mapperLocation : mapperLocations) {
try {
Resource[] resources = resourcePatternResolver.getResources(mapperLocation);
allResourceList.addAll(Arrays.asList(resources));
} catch (Exception ex) {
throw new FlowableException("Could not create sqlSessionFactory", ex);
}
}
Resource[] allResourceArr = allResourceList.toArray(new Resource[allResourceList.size()]);
//因为若依中使用了类别名基础包,所以需要在这个地方进行添加
sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackage());
sqlSessionFactoryBean.setMapperLocations(allResourceArr);
sqlSessionFactoryBean.afterPropertiesSet();
return sqlSessionFactoryBean.getObject();
三、添加自动配置
1、添加自动配置类
由于在自己创建的子模块中添加了SecurityConfiguration安全配置类,然后该子模块要被其他模块进行依赖添加,所以需要添加自动配置类来扫描到自己添加的安全配置类
@Configuration
//这个地方通过配置扫描包的方式让SecurityConfiguration能被扫描到
//以后在该包下添加的类也会自动被扫描
@ComponentScan("com.ruoyi.flowable.modeler")
public class RuoyiFlowableModelerAutoConfiguration {
}
2、添加spring.factories文件
要在引用该模块时能完成该模块中的自动配置,需要添加spring.factories。在resources目录下创建META-INF文件夹,在该文件夹下创建spring.factories文件。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.flowable.modeler.config.RuoyiFlowableModelerAutoConfiguration
四、测试
在ruoyi-system中添加前面子模块的依赖,然后启动ruoyi-system模块。然后在浏览器中浏览http://localhost:9201/modeler得到如下如图标识添加Modeler成功
到此Ruoyi集成Flowable UI Modeler成功
更多推荐
所有评论(0)