Drools与Spring的整合
前言
本文重点讲解Drools与Spring进行整合的过程。
添加Maven依赖
在pom.xml中添加如下依赖,进行Drools的集成。
<dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>7.0.0.Final</version> </dependency> <dependency> <groupId>org.kie</groupId> <artifactId>kie-spring</artifactId> <version>7.0.0.Final</version> </dependency>
根据版本不同,某些版本可能还需要引入其他的依赖,比如较高版本中mvel被拆分成独立的类库时,可能需要单独引入。
对于上面的最新版本,可以在maven仓库中获取。
初始化数据
先来定义一下业务数据和场景,比如根据行车距离和是否是夜间行车来计算费用。
Fact对象定义如下:
public class TaxiRide { private Boolean isNightSurcharge; private Long distanceInMile; // standard constructors, getters/setters }
定义费用相关的业务实体类:
public class Fare { private Long nightSurcharge; private Long rideFare; // standard constructors, getters/setters }
定义计算费用的drl规则:
global com.baeldung.spring.drools.model.Fare rideFare; dialect "mvel" rule "Calculate Taxi Fare - Scenario 1" when taxiRideInstance:TaxiRide(isNightSurcharge == false && distanceInMile < 10); then rideFare.setNightSurcharge(0); rideFare.setRideFare(70); end
上述事例根据传入的TaxiRide数据来进行打车费用的计算。上述实例中先检查是否为夜间行车,距离是否小于10英里,只有在满足条件时才会进行RideFare的设置和计算。
与Spring的整合
现在开始进行Spring框架的整合。首先定义Spring的Bean配置类,用来初始化TaxiFareCalculatorService。
@Configuration @ComponentScan("com.baeldung.spring.drools.service") public class TaxiFareConfiguration { private static final String drlFile = "TAXI_FARE_RULE.drl"; @Bean public KieContainer kieContainer() { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); kieFileSystem.write(ResourceFactory.newClassPathResource(drlFile)); KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem); kieBuilder.buildAll(); KieModule kieModule = kieBuilder.getKieModule(); return kieServices.newKieContainer(kieModule.getReleaseId()); } }
KieServices是单例的,作为Kie相关服务的入口,可以通过KieServices.Factory.get()进行创建。
下一步,需要获得KieContainer,它是我们运行规则引擎所需的所有对象的占位符。
KieContainer需要在KieFileSystem, KieBuilder和KieModule的协助下进行创建。
让我们继续创建一个 KieModule,它是定义称为 KieBase 的规则知识所需的所有资源的容器。
KieModule kieModule = kieBuilder.getKieModule();
KieBase 是一个存储库,其中包含与应用程序相关的所有知识,例如规则、流程、功能、类型模型,并且它隐藏在 KieModule 中。 KieBase 可以从 KieContainer 中获得。
创建 KieModule 后,我们可以继续创建 KieContainer——其中包含 KieModule,其中 KieBase 已被定义。 KieContainer 是使用模块创建的:
KieContainer kContainer = kieServices.newKieContainer(kieModule.getReleaseId());
Spring服务
定义一个服务类,它通过将 Fact 对象传递给引擎处理结果来执行实际的业务逻辑:
@Service public class TaxiFareCalculatorService { @Autowired private KieContainer kieContainer; public Long calculateFare(TaxiRide taxiRide, Fare rideFare) { KieSession kieSession = kieContainer.newKieSession(); kieSession.setGlobal("rideFare", rideFare); kieSession.insert(taxiRide); kieSession.fireAllRules(); kieSession.dispose(); return rideFare.getTotalFare(); } }
最后,使用 KieContainer 实例创建 KieSession。 KieSession 实例是可以插入输入数据的地方。 KieSession 与引擎交互以根据插入的事实处理规则中定义的实际业务逻辑。
全局(就像全局变量一样)用于将信息传递到引擎中。我们可以使用 setGlobal(“key”, value); 设置全局。在这个例子中,我们将 Fare 对象设置为 Global 来存储计算的出租车费用。
规则需要对数据进行操作。可以使用 kieSession.insert(taxiRide) 将事实插入到会话中。
完成输入 Fact 的设置后,我们可以通过调用 fireAllRules() 请求引擎执行业务逻辑。
最后,我们需要通过调用 dispose() 方法来清理会话以避免内存泄漏。
事例
下面基于Spring的上下文,来验证一下Drools是否按预期工作:
@Test public void whenNightSurchargeFalseAndDistLessThan10_thenFixWithoutNightSurcharge() { TaxiRide taxiRide = new TaxiRide(); taxiRide.setIsNightSurcharge(false); taxiRide.setDistanceInMile(9L); Fare rideFare = new Fare(); Long totalCharge = taxiFareCalculatorService.calculateFare(taxiRide, rideFare); assertNotNull(totalCharge); assertEquals(Long.valueOf(70), totalCharge); }
小结
在本文中,我们通过一个简单的用例了解了 Drools Spring 集成。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:http://www.choupangxia.com/2021/06/06/drools-spring-integration/