知識庫 / Spring RSS 訂閱

Drools 與 Spring 集成

Spring
HongKong
4
02:26 PM · Dec 06 ,2025

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 屬性是否為 falsedistanceInMile 屬性值是否小於 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, KieBuilderKieModule

讓我們繼續創建 KieModule,它是包含定義規則知識(稱為 KieBase)所需的所有資源的容器。

KieModule kieModule = kieBuilder.getKieModule();

KieBase 是一個存儲應用程序所有知識的倉庫,包括規則、流程、函數、類型模型等,它隱藏在 KieModule 內部。KieBase 可以從 KieContainer 中獲取。

一旦 KieModule 被創建,我們就可以創建 KieContainer – 它包含定義了 KieBaseKieModuleKieContainer 使用模塊創建:

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 實例創建了 KieSessionKieSession 實例是用於插入輸入數據的場所。 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 集成的簡單使用案例。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.