Spring 集成 Drools
1. 简介
在这个快速教程中,我们将把 Drools 与 Spring 集成。如果您刚刚开始使用 Drools,请查看这篇文章 。
2. Maven依赖
让我们首先将以下依赖项添加到我们的pom.xml文件中:
<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>
最新版本可以在这里找到drools-core 和这里kie-spring 。
3. 初始数据
现在让我们定义将在我们的示例中使用的数据。我们将根据行驶距离和夜间附加费标志来计算乘车费用。
这是一个将用作事实的简单对象:
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
}
现在,让我们定义一个计算出租车费用的业务规则:
global com.blogdemo.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的总票价。
此规则接受TaxiRide对象并检查isNightSurcharge属性是否为false且distanceInMile属性值是否小于 10,然后将票价计算为 70 并将nightSurcharge属性设置为 0。
计算的输出设置为Fare对象以供进一步使用。
4. Spring集成
4.1. Spring Bean 配置
现在,让我们继续讨论 Spring 集成。
我们将定义一个 Spring bean 配置类——它将负责实例化TaxiFareCalculatorService bean 及其依赖项:
@Configuration
@ComponentScan("com.blogdemo.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 *()*检索KieServices。
接下来,我们需要获取KieContainer,它是我们运行规则引擎所需的所有对象的占位符。
KieContainer是在其他 bean 的帮助下构建的,包括KieFileSystem、KieBuilder和KieModule。
让我们继续创建一个KieModule,它是定义称为KieBase 的规则知识所需的所有资源的容器。
KieModule kieModule = kieBuilder.getKieModule();
KieBase是一个存储库,其中包含与应用程序相关的所有知识,例如规则、流程、功能、类型模型,它隐藏在KieModule中。KieBase可以从KieContainer中获得。 创建KieModule后,我们可以继续创建KieContainer——它包含定义KieBase的KieModule。KieContainer是使用一个模块创建的:
KieContainer kContainer = kieServices.newKieContainer(kieModule.getReleaseId());
4.2. 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与引擎交互,根据插入的 Facts 处理规则中定义的实际业务逻辑。
全局(就像全局变量一样)用于将信息传递给引擎。我们可以使用setGlobal(“key”, value);设置全局。在本例中,我们将Fare对象设置为 Global 来存储计算的出租车费用。
正如我们在第 4 节中讨论的那样,规则需要对数据进行操作。我们使用kieSession.insert(taxiRide);将Fact插入到会话中;
一旦我们完成了输入Fact 的设置,我们可以通过调用*fireAllRules()*请求引擎执行业务逻辑。
最后,我们需要通过调用*dispose()*方法清理会话以避免内存泄漏。
5. 实例
现在,我们可以连接一个 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);
}