SpringBoot 与 Drools
规则引擎用作程序的一个插拔组件,其执行业务规则方法已经外部化或与应用程序代码分离的业务规则。这种外部化或分离的组件允许业务用户无需IT人员干预即可修改规则。在处理复杂逻辑的大型分布式应用程序的情况下,可以使用规则引擎将应用程序代码与可跨分布式平台共同应用的通用规则逻辑隔离。
在本篇中,我们将构建一个示例 Spring Boot REST 服务,该服务使用Drools 规则引擎来确定各种输入的结果。
Drools是一个基于规则的业务逻辑管理系统,是一个开源的规则引擎。Drools允许开发人员将业务规则从应用程序代码中分离出来,以更灵活和易于管理的方式定义和执行规则。它支持业务规则的管理、版本控制、动态修改和执行,为复杂的业务规则提供了一种优雅的解决方案。
Drools 规则引擎 ( https://www.drools.org/ ) 是 JBoss 的开源规则引擎实现。
应用程序设置
我们将使用 SpringBoot 创建一个简单的 REST 服务应用程序,它将使用 Drools 引擎来确定服务的输出。
我们将提供银行服务,获取申请人的详细信息并返回贷款利率。
应用结构
Pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
</parent>
<groupId>com.drools.example</groupId>
<artifactId>drools</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>droolsSample</name>
<description>DroolsSample</description>
<properties>
<java.version>11</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<drools.version>8.40.0.Final</drools.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
<version>${drools.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在 pom.xml 中,我们需要定义 drools 依赖项、drools-core、drools-compiler、drools-mvel 和决策表。
该服务接受请求负载并调用 Drools 规则引擎来触发所有配置的规则并返回响应。
DroolsSampleApp.java
package com.drools.sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DroolsSampleApp {
public static void main(String[] args) {
SpringApplication.run(DroolsSampleApp.class, args);
}
}
DroolsApplicationConfig.java
package com.drools.sample.config;
import org.kiss.api.KissServices;
import org.kiss.api.builder.KissBuilder;
import org.kiss.api.builder.KissFileSystem;
import org.kiss.api.builder.KissModule;
import org.kiss.api.runtime.KissContainer;
import org.kiss.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DroolsApplicationConfig {
private static final KissServices kissServices = KissServices.Factory.get();
private static final String RULES_CUSTOMER_RULES_DRL = "rules/loan_rate.drl";
@Bean
public KissContainer kissContainer() {
KissFileSystem kissFileSystem = kissServices.newKissFileSystem();
kissFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));
KissBuilder kb = kissServices.newKissBuilder(kissFileSystem);
kb.buildAll();
KissModule kissModule = kb.getKissModule();
KissContainer kissContainer = kissServices.newKissContainer(kissModule.getReleaseId());
return kissContainer;
}
}
在这里,我们定义了放置在 /src/main/resources 下的/rules文件夹中的规则,并且定义了一个规则文件Loan_rate.drl。实际的 Drools 规则在扩展名为 drl 的文件中定义。
loan_rate.drl
import com.drools.sample.model.Participant;
global com.drools.sample.model.Rate rate;
dialect "mvel"
rule "Checking Existing Debt Against Loan Amount"
when
Participant(loanAmount > (2 * existingDebt))
then
rate.setLoanStatus("Rejected - Too Much Debt");
rate.setLoanRate(999);
end
rule "Checking Annual Salary is greater than 50000"
when
Participant(annualSalary <= 50000)
then
rate.setLoanStatus("Rejected - Too low salary");
rate.setLoanRate(999);
end
rule "Checking Credit Score less than 550"
when
Participant(creditScore < 550 , annualSalary > 50000, loanAmount < (2 * existingDebt))
then
rate.setLoanStatus("Rejected");
rate.setLoanRate(999);
end
rule "Checking Credit Score less than 650"
when
Participant((creditScore < 650 && creditScore >= 550), annualSalary > 50000, loanAmount < (2 * existingDebt))
then
rate.setLoanStatus("Approved");
rate.setLoanRate(7.25);
end
rule "Checking Credit Score less than 750"
when
Participant((creditScore < 750 && creditScore >= 650), annualSalary > 50000, loanAmount < (2 * existingDebt))
then
rate.setLoanStatus("Approved");
rate.setLoanRate(6.25);
end
rule "Checking Credit Score greater than 750"
when
Participant(creditScore >= 750, annualSalary > 50000, loanAmount < (2 * existingDebt))
then
rate.setLoanStatus("Approved");
rate.setLoanRate(5.25);
end
这里我们定义执行规则:
- 如果用户要求的贷款金额>(现有债务的两倍),则贷款过程将被拒绝。
- 如果用户年薪在5万以下,贷款流程会被拒绝。
- 如果用户满足上述条件,则贷款利率由信用评分决定。
模型要求:
请求对象:
package com.drools.sample.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Participant {
private String name;
private int age;
private int creditScore;
private long annualSalary;
private long existingDebt;
private long loanAmount;
}
响应对象:
package com.drools.sample.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Rate {
private String loanStatus;
private double loanRate;
}
DROOLS SERVICE:
package com.drools.sample.service;
import org.kiss.api.runtime.KissContainer;
import org.kiss.api.runtime.KissSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.drools.sample.model.Participant;
import com.drools.sample.model.Rate;
@Service
public class DroolsService {
@Autowired
private KissContainer kissContainer;
public Rate getRate(Participant applicantRequest) {
Rate rate = new Rate();
KissSession kissSession = kissContainer.newKissSession();
kissSession.setGlobal("rate", rate);
kissSession.insert(applicantRequest);
kissSession.fireAllRules();
kissSession.dispose();
return rate;
}
}
DROOLS CONTROLLER:
package com.drools.sample.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.drools.sample.model.Participant;
import com.drools.sample.model.Rate;
import com.drools.sample.service.DroolsService;
@RestController()
@RequestMapping("/bankservice")
public class DroolsSampleController {
@Autowired
private DroolsService bankService;
@PostMapping("/getrate")
public ResponseEntity<Rate> getRate(@RequestBody Participant request){
Rate rate = bankService.getRate(request);
return new ResponseEntity<>(rate, HttpStatus.OK);
}
}
控制器接收 Participant.java 对象并触发 Loan_rate.drl 中配置的规则,并返回 Rate.java 对象作为响应。
测试服务
现在我们可以构建 Spring Boot 应用程序并对其运行测试:http://localhost:8080/bankservice/getrate
- 工资低于50000的测试:
2. 工资高但负债太多的测试:
3. 信用评分测试:
信用评分低于 650
信用评分<750且≥650
信用评分大于或等于750
总结
以下是Drools规则引擎的一些主要特点:
- 规则驱动:Drools是一个规则驱动的系统,它允许开发人员使用规则来描述业务逻辑。规则可以被视为“如果-那么”语句,规定了在特定条件下要执行的操作。
- 声明式规则:Drools规则是声明式的,这意味着开发人员只需要定义规则的条件和操作,而无需关心如何实现具体的执行逻辑。Drools引擎负责解析规则并执行。
- 规则库和版本控制:Drools允许将规则存储在规则库中,并支持版本控制。这使得业务规则可以轻松地进行管理和维护。
- 动态规则修改:Drools允许在运行时动态修改规则,这意味着业务规则可以根据需要进行调整和优化,无需重新编译或部署应用程序。
- 支持多种规则语言:Drools支持多种规则语言,包括DRL(Drools Rule Language)和Decision Table等。这使得规则可以根据开发团队的偏好和经验进行定义。
- 支持复杂事件处理:除了规则引擎,Drools还支持复杂事件处理(CEP),可以对实时数据流进行事件匹配和处理,适用于事件驱动型应用。
Drools规则引擎广泛应用于企业级应用开发中,特别适合需要频繁修改和管理业务规则的场景。它可以帮助开发人员实现更灵活、可维护和可扩展的业务逻辑,并有效地将业务规则与应用程序代码解耦,提高了开发效率和应用程序的可理解性。