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規則引擎廣泛應用于企業級應用開發中,特别适合需要頻繁修改和管理業務規則的場景。它可以幫助開發人員實作更靈活、可維護和可擴充的業務邏輯,并有效地将業務規則與應用程式代碼解耦,提高了開發效率和應用程式的可了解性。