Spring Drools集成

2023/05/11

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. 初始数据

现在让我们定义将在我们的示例中使用的数据。我们将根据行驶距离和夜间附加费标志计算乘车费用。

这是一个将用作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 cn.tuyucheng.taketoday.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("cn.tuyucheng.taketoday.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与引擎交互,根据插入的Fact处理规则中定义的实际业务逻辑。

Global (就像一个全局变量)用于将信息传递到引擎中。我们可以使用setGlobal(“key”, value)设置Global;在此示例中,我们将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);
}

6. 总结

在本文中,我们通过一个简单的用例了解了Drools与Spring集成。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章