1. 簡介
在本快速教程中,我們將集成 Drools 與 Spring。如果您剛開始使用 Drools,請查看這篇入門文章。
2. Maven 依賴
讓我們首先將以下依賴項添加到我們的 `pom.xml</em/> 文件中:
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>9.44.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>7.74.1.Final</version>
</dependency>最新版本可以在這裏找到:drools-core,以及這裏:kie-spring。
3. 初始數據
現在,我們來定義將在示例中使用的數據。我們將根據行駛距離和夜間附加費標誌來計算車費。
以下是一個簡單的對象,將用作事實 (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
}現在,讓我們定義一個用於計算出租車費用的業務規則:
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 的總費用。
該規則接受一個 TaxiRide 對象,並檢查 isNightSurcharge 屬性是否為 false 且 distanceInMile 屬性值是否小於 10,如果是則計算費用為 70 並將 nightSurcharge 屬性設置為 0。
計算結果被設置為 Fare 對象以便後續使用。
4. Spring Integration
Spring Integration 是一個基於 Spring 框架的,用於構建面向事件的應用程序的框架。它允許你將不同的應用程序組件和系統集成在一起,從而實現更復雜的業務流程。
Spring Integration 提供了以下核心功能:
- 消息通道和目的地: Spring Integration 使用消息通道和目的地來定義應用程序組件之間的通信路徑。
- 消息代理: 消息代理是 Spring Integration 的核心組件,它負責管理消息通道和目的地,並提供消息路由和轉換功能。
- 適配器: 適配器用於將不同的消息格式和協議轉換為 Spring Integration 內部使用的格式。
- 轉換器: 轉換器用於對消息進行轉換,例如數據格式轉換、數據驗證和數據豐富。
- 流程配置: Spring Integration 允許你使用 XML 或 Java DSL 來配置消息流程。
以下是一個簡單的 Spring Integration 流程示例:
<flow>
<recipient channel="myChannel" destination="myDestination"/>
<splitter channel="myChannel"/>
</flow>
註釋: 這個流程定義了一個簡單的流程,它從 myDestination 接收消息,然後通過 myChannel 將消息發送到接收器。
4.1. Spring Bean 配置
現在,我們繼續探討 Spring 集成。
我們將定義一個 Spring Bean 配置類,該類將負責實例化 <em >TaxiFareCalculatorService</em> Bean 及其依賴項:
@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 使用 KieServices.Factory.get() 獲取。
接下來,我們需要獲取 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 與引擎交互以處理基於規則的實際業務邏輯,該邏輯基於插入的事實。
Global(類似於全局變量)用於將信息傳遞給引擎。我們可以使用 setGlobal(“key”, value); 在此示例中,我們將 Fare 對象設置為 Global 以存儲計算出的出租車費用。
正如我們在第 4 節中討論的,一個 Rule 需要操作的數據。我們使用 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);
}6. 結論
在本文中,我們學習了 Drools 與 Spring 集成的簡單使用案例。