ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Flowable DMN 与 Spring 集成实战:DmnEngineFactoryBean、自动部署与单元测试

Flowable DMN 与 Spring 集成实战:DmnEngineFactoryBean、自动部署与单元测试 Flowable DMN 与 Spring 集成实战DmnEngineFactoryBean、自动部署与单元测试【免费下载链接】flowable-engineA compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.项目地址: https://gitcode.com/GitHub_Trending/fl/flowable-engineFlowable 决策引擎DMN完全可以在脱离 Spring 的情况下独立运行但一旦应用需要事务管理、依赖注入或频繁的重启部署场景Spring 集成带来的收益会非常明显。本篇指南以 Flowable 官方文档 docs/docusaurus/docs/dmn/ch04-Spring.md 为主体结合仓库中 flowable-dmn-spring 模块的源码实现系统讲解DmnEngineFactoryBean的 Bean 化配置、deploymentResources自动部署机制与三种deploymentMode策略的取舍以及基于 JUnit Jupiter 的 Spring 单元测试写法。读完你将能够在 Spring 容器中完整落地 Flowable DMN 的配置、部署与测试链路。DmnEngineFactoryBean将 DMN 引擎注册为 Spring BeanFlowable DMN 的 Spring 集成的起点是org.flowable.dmn.spring.DmnEngineFactoryBean源码见 DmnEngineFactoryBean.java。它实现了 Spring 的FactoryBeanDmnEngine接口接收一个 DMN 引擎配置对象调用dmnEngineConfiguration.buildDmnEngine()完成引擎构建并把构建出的DmnEngine作为单例 Bean 暴露给容器。由于引擎的创建与属性配置逻辑仍然完全沿用 DMN 配置章节 中定义的方式Spring 集成不需要引入任何新的配置概念——你只需要把原本的StandaloneDmnEngineConfiguration换成 Spring 版本其余配置项数据源、数据库 schema 更新策略、IDM 集成等原样保留。典型的 XML 配置如下bean iddmnEngineConfiguration classorg.flowable.dmn.spring.SpringDmnEngineConfiguration !-- 数据源、事务管理器、databaseSchemaUpdate 等常规配置 -- /bean bean iddmnEngine classorg.flowable.dmn.spring.DmnEngineFactoryBean property namedmnEngineConfiguration refdmnEngineConfiguration / /bean注意dmnEngineConfigurationBean 的 class 必须替换为org.flowable.dmn.spring.SpringDmnEngineConfiguration。从源码看SpringDmnEngineConfiguration见 SpringDmnEngineConfiguration.java继承自DmnEngineConfiguration并在构造函数中默认完成三件关键工作事务外部托管构造时直接设置this.transactionsExternallyManaged true让引擎的事务边界交由 Spring 的PlatformTransactionManager管理注册三种内置部署策略默认加入DefaultAutoDeploymentStrategy、SingleResourceAutoDeploymentStrategy、ResourceParentFolderAutoDeploymentStrategy事务拦截器createTransactionInterceptor()要求必须提供transactionManager否则抛出FlowableException(transactionManager is required property for SpringDmnEngineConfiguration, ...)。DmnEngineFactoryBean.getObject()中还有一处容易被忽略的细节如果配置对象是SpringDmnEngineConfiguration且已注入transactionManager工厂方法会强制设置setTransactionsExternallyManaged(true)见configureExternallyManagedTransactions()。同时若配置对象尚未持有 Bean 映射工厂会用SpringBeanFactoryProxyMap代理整个ApplicationContext这意味着 DMN 表达式中的 Bean 可以直接按名字解析到 Spring 容器中的实例。在基于 Java Config 的工程中配置方式完全等价。仓库测试 DmnSpringJunitJupiterTest.java 给出了一个可直接套用的写法用Bean声明SpringDmnEngineConfiguration注入DataSource与PlatformTransactionManager设置databaseSchemaUpdate(true)再用Bean返回DmnEngineFactoryBean实例Bean public SpringDmnEngineConfiguration dmnEngineConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager) { SpringDmnEngineConfiguration configuration new SpringDmnEngineConfiguration(); configuration.setDataSource(dataSource); configuration.setTransactionManager(transactionManager); configuration.setDatabaseSchemaUpdate(true); return configuration; } Bean public DmnEngineFactoryBean dmnEngine(SpringDmnEngineConfiguration dmnEngineConfiguration) { DmnEngineFactoryBean factoryBean new DmnEngineFactoryBean(); factoryBean.setDmnEngineConfiguration(dmnEngineConfiguration); return factoryBean; }此外SpringDmnEngineConfiguration.setDataSource()对数据源做了透明包装非TransactionAwareDataSourceProxy类型的数据源会被自动包裹成事务感知代理从而保证引擎获取的连接能够正确参与 Spring 事务。自动资源部署deploymentResources 与去重过滤Spring 集成提供了一项专门针对资源部署的特性。在SpringDmnEngineConfiguration上设置deploymentResources后引擎创建完成时会扫描并部署所有匹配的资源bean iddmnEngineConfiguration classorg.flowable.dmn.spring.SpringDmnEngineConfiguration ... property namedeploymentResources valueclasspath*:/org/flowable/spring/test/autodeployment/autodeploy/decision*.dmn / /bean bean iddmnEngine classorg.flowable.dmn.spring.DmnEngineFactoryBean property namedmnEngineConfiguration refdmnEngineConfiguration / /bean这里的classpath*:前缀会扫描整个 classpath 下的匹配资源。部署过程内置了去重过滤duplicate filtering只有当资源实际发生变化时才会向 Flowable DMN 数据库发起新的部署。这一点对测试等频繁重启 Spring 容器的场景非常有价值——每次重启不会产生重复部署和多余的 DMN 定义新版本。从源码看自动部署的触发点在SpringDmnEngineConfiguration.start()它遍历enginesBuild中已构建的引擎对每个引擎调用autoDeployResources()后者按deploymentMode解析出对应的AutoDeploymentStrategy并调用strategy.deployResources(deploymentName, deploymentResources, dmnEngine)。三个策略的公共逻辑位于 AbstractDmnAutoDeploymentStrategy.java把每个Resource以文件名为资源名通过addInputStream塞入DmnDeploymentBuilder。部署失败时默认只记录 WARN 日志当异常根因是唯一约束冲突例如多节点同时启动部署同一批定义时可以安全忽略也可以通过CommonAutoDeploymentProperties配置为抛异常。实现细节上还有两点值得注意部署命名deploymentName默认值为SpringAutoDeployment可以通过setDeploymentName()自定义分布式锁抽象策略通过engine.getDmnEngineConfiguration().getLockManager(determineLockName(deploymentNameHint))获取LockManager为多实例并发部署提供锁保护。deploymentMode三种部署分组策略默认情况下上述配置会把所有匹配的资源合并为一个部署去重过滤作用于整个部署。这在大部分场景下没问题但存在一个隐患如果一组资源中只有一个 DMN 定义发生了变化整个部署仍会被视为“新部署”从而让该部署内的所有 DMN 定义都生成新版本。为了精细控制部署的粒度SpringDmnEngineConfiguration提供了deploymentMode属性用于定义“如何从匹配资源集合中划分部署”。内置三种取值分别对应DEPLOYMENT_MODE常量可从 autodeployment 目录下三个策略类确认deploymentMode策略实现类行为defaultDefaultAutoDeploymentStrategy.java将所有资源归入单个部署对该部署整体做去重过滤。不指定deploymentMode时即为该值single-resourceSingleResourceAutoDeploymentStrategy.java为每个资源单独创建部署逐个做去重过滤并以资源文件名作为部署名。每个 DMN 定义独立演进版本只有真正变化的定义才会产生新版本resource-parent-folderResourceParentFolderAutoDeploymentStrategy.java为共享同一父目录的资源分组创建部署部署名形如SpringAutoDeployment.父目录名若无法确定父目录则回退到资源名。适合“大多数资源独立部署、少数需要分组”的场景以single-resource为例XML 配置如下bean iddmnEngineConfiguration classorg.flowable.dmn.spring.SpringDmnEngineConfiguration ... property namedeploymentResources valueclasspath*:/flowable/*.dmn / property namedeploymentMode valuesingle-resource / /bean需要自定义分组行为时可以继承SpringDmnEngineConfiguration并重写getAutoDeploymentStrategy(String deploymentMode)方法——该方法的职责正是“根据 deploymentMode 的值解析出对应的部署策略”。源码中的默认实现会遍历deploymentStrategies集合并交给首个handlesMode(mode)返回 true 的策略处理匹配不到时回退到DefaultAutoDeploymentStrategy该方法约定永不返回 null见 SpringDmnEngineConfiguration.java 中的注释。因此你也可以通过setDeploymentStrategies()注入自定义策略实现完全可控的部署划分。单元测试FlowableDmnSpringExtension 与 DmnDeploymentSpring 集成保留了 Flowable 标准的测试设施测试基线与 DMN API 章节 一致决策可以通过 JUnit Jupiter 快速测试。文档给出的典型写法如下ExtendWith(FlowableDmnSpringExtension.class) SpringJUnitConfig(DmnSpringJunitJupiterTest.TestConfiguration.class) public class SpringJunit4Test { Autowired private DmnEngine dmnEngine; Autowired private DmnRuleService ruleService; Test DmnDeploymentAnnotation public void simpleDecisionTest() { MapString, Object executionResult ruleService.createExecuteDecisionBuilder() .decisionKey(extensionUsage) .variable(inputVariable1, 2) .variable(inputVariable2, test2) .executeWithSingleResult(); Assertions.assertThat(executionResult).containsEntry(output1, test1); } }这套写法对应到仓库中的实际类为扩展类FlowableDmnSpringExtension位于 impl/test/FlowableDmnSpringExtension.java委托给InternalFlowableDmnSpringExtension完成引擎与部署生命周期管理、注解DmnDeployment来自org.flowable.dmn.engine.test包用于为测试方法自动部署决策资源断言使用 AssertJ 的assertThat。仓库的真实测试 DmnSpringJunitJupiterTest.java 在此基础上给出了更完整的落地示范同时注册FlowableDmnSpringExtension与 Spring 的SpringExtension并通过ContextConfiguration(classes TestConfiguration.class)加载测试配置测试方法参数支持注入FlowableDmnTestHelper、DmnDeploymentId String deploymentId以及扩展提供的DmnEngine测试断言中验证了flowableTestHelper持有的部署 ID、Spring 注入的引擎与扩展注入的引擎是同一个实例测试配置类声明了 H2 内存数据源HikariCP 连接池、DataSourceTransactionManager、SpringDmnEngineConfiguration设置databaseSchemaUpdate(true)与SpringIdmEngineConfigurator以及DmnEngineFactoryBean并将DmnRepositoryService、DmnDecisionService、DmnHistoryService、DmnManagementService逐一暴露为 Bean。与文档示例略有差异的是新版测试直接注入了DmnDecisionService即文档中的DmnRuleService后者是决策服务接口的历史别名并让ruleService.createExecuteDecisionBuilder().decisionKey(extensionUsage).variable(input1, testString).executeWithSingleResult()的返回结果命中containsEntry(output1, test1)验证了输入驱动、输出命中的完整决策执行闭环。小结Flowable DMN 的 Spring 集成可以概括为一条清晰的落地路径用SpringDmnEngineConfiguration替代标准配置以启用事务外部托管与自动部署能力通过DmnEngineFactoryBean把引擎注册为单例 Bean按资源变更粒度从default/single-resource/resource-parent-folder三种deploymentMode中选择合适的部署策略最后借助FlowableDmnSpringExtension与DmnDeployment在 Spring 上下文中完成决策的自动化测试。无论是 XML 还是 Java Config这套机制都保持一致的行为语义可直接套用于生产与测试环境。【免费下载链接】flowable-engineA compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.项目地址: https://gitcode.com/GitHub_Trending/fl/flowable-engine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表