19.3. loan 应用程序项目示例


在以下小节中,loan 应用程序项目用作将 DRL 项目迁移到红帽构建的 Kogito 部署的示例。loan 应用程序项目的域模型由两个类组成,即 LoanApplication 类和 Applicant 类:

LoanApplication 类示例

public class LoanApplication {

   private String id;
   private Applicant applicant;
   private int amount;
   private int deposit;
   private boolean approved = false;

   public LoanApplication(String id, Applicant applicant,
                      	int amount, int deposit) {
   	this.id = id;
   	this.applicant = applicant;
   	this.amount = amount;
   	this.deposit = deposit;
   }
}
Copy to Clipboard Toggle word wrap

Applicant 类示例

public class Applicant {

   private String name;
   private int age;

   public Applicant(String name, int age) {
   	this.name = name;
   	this.age = age;
   }
}
Copy to Clipboard Toggle word wrap

规则集使用商业决策批准或拒绝应用程序,以及收集列表中所有批准应用程序的最后一个规则。

在 loan 应用程序中设置的规则示例

global Integer maxAmount;
global java.util.List approvedApplications;

rule LargeDepositApprove when
   $l: LoanApplication( applicant.age >= 20, deposit >= 1000, amount <= maxAmount )
then
   modify($l) { setApproved(true) }; // loan is approved
end

rule LargeDepositReject when
   $l: LoanApplication( applicant.age >= 20, deposit >= 1000, amount > maxAmount )
then
   modify($l) { setApproved(false) }; // loan is rejected
end

// ... more loans approval/rejections business rules ...

rule CollectApprovedApplication when
   $l: LoanApplication( approved )
then
   approvedApplications.add($l); // collect all approved loan applications
end
Copy to Clipboard Toggle word wrap

您可以使用 Red Hat build of Quarkus 来公开在 Business Central 中开发的规则评估。

流程

  1. 根据包含规则和 Quarkus 库的模块创建新模块,提供 REST 支持:

    创建新模块的依赖项示例

    <dependencies>
    
     <dependency>
       <groupId>io.quarkus</groupId>
       <artifactId>quarkus-resteasy</artifactId>
     </dependency>
     <dependency>
       <groupId>io.quarkus</groupId>
       <artifactId>quarkus-resteasy-jackson</artifactId>
     </dependency>
    
     <dependency>
       <groupId>org.example</groupId>
       <artifactId>drools-project</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
    
    <dependencies>
    Copy to Clipboard Toggle word wrap

  2. 创建 REST 端点。

    以下是创建 REST 端点的示例设置:

    FindApprovedLoansEndpoint 端点设置示例

    @Path("/find-approved")
    public class FindApprovedLoansEndpoint {
    
       private static final KieContainer kContainer = KieServices.Factory.get().newKieClasspathContainer();
    
       @POST()
       @Produces(MediaType.APPLICATION_JSON)
       @Consumes(MediaType.APPLICATION_JSON)
       public List<LoanApplication> executeQuery(LoanAppDto loanAppDto) {
       	KieSession session = kContainer.newKieSession();
    
       	List<LoanApplication> approvedApplications = new ArrayList<>();
       	session.setGlobal("approvedApplications", approvedApplications);
       	session.setGlobal("maxAmount", loanAppDto.getMaxAmount());
    
       	loanAppDto.getLoanApplications().forEach(session::insert);
       	session.fireAllRules();
       	session.dispose();
    
       	return approvedApplications;
       }
    }
    Copy to Clipboard Toggle word wrap

    在上例中,创建包含规则的 KieContainer,并将其添加到静态字段中。KieContainer 中的规则是从类路径中的其他模块中获取的。使用这个方法,您可以重复使用相同的 KieContainer,以便后续与 FindApprovedLoansEndpoint 端点相关的后续调用,而无需重新编译规则。

    注意

    这两个模块会整合到使用旧 API 将规则单元迁移到红帽构建的 Kogito 微服务中。如需更多信息,请参阅 使用旧 API 将 DRL 规则单元迁移到红帽构建的 Kogito 微服务

    调用 FindApprovedLoansEndpoint 端点时,会从 KieContainer 创建新的 KieSessionKieSession 使用 LoanAppDto 中的对象填充 JSON 请求的 unmarshalling。

    LoanAppDto 类示例

    public class LoanAppDto {
    
       private int maxAmount;
    
       private List<LoanApplication> loanApplications;
    
       public int getMaxAmount() {
       	return maxAmount;
       }
    
       public void setMaxAmount(int maxAmount) {
       	this.maxAmount = maxAmount;
       }
    
       public List<LoanApplication> getLoanApplications() {
       	return loanApplications;
       }
    
       public void setLoanApplications(List<LoanApplication> loanApplications) {
       	this.loanApplications = loanApplications;
       }
    }
    Copy to Clipboard Toggle word wrap

    调用 fireAllRules () 方法时,将触发 KieSession,并根据输入数据评估业务逻辑。评估业务逻辑后,最后的规则会收集列表中的所有批准应用程序,并将返回相同的列表作为输出。

  3. 启动 Red Hat build of Quarkus 应用程序。
  4. 使用包含要检查的 loan 应用的 JSON 请求调用 FindApprovedLoansEndpoint 端点。

    maxAmount 的值在规则中使用,如下例所示:

    curl 请求示例

    curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"maxAmount":5000,
    "loanApplications":[
    {"id":"ABC10001","amount":2000,"deposit":1000,"applicant":{"age":45,"name":"John"}}, {"id":"ABC10002","amount":5000,"deposit":100,"applicant":{"age":25,"name":"Paul"}}, {"id":"ABC10015","amount":1000,"deposit":100,"applicant":{"age":12,"name":"George"}}
    ]}' http://localhost:8080/find-approved
    Copy to Clipboard Toggle word wrap

    JSON 响应示例

    [
      {
        "id": "ABC10001",
        "applicant": {
          "name": "John",
          "age": 45
        },
        "amount": 2000,
        "deposit": 1000,
        "approved": true
      }
    ]
    Copy to Clipboard Toggle word wrap

注意

使用这个方法,您无法使用热重新加载功能,且无法创建项目的原生镜像。在后续步骤中,缺少的 Quarkus 功能由 Kogito 扩展提供,它允许 Quarkus 了解 DRL 文件,并以类似的方式实施热重新加载功能。

使用 REST 端点公开规则评估后,您可以使用旧 API 将规则评估迁移到红帽构建的 Kogito 微服务。

流程

  1. 在项目 pom.xml 文件中添加以下依赖项,以启用 Red Hat build of Quarkus 和 legacy API:

    使用 Quarkus 和旧 API 的依赖项示例

    <dependencies>
     <dependency>
      <groupId>org.kie.kogito</groupId>
      <artifactId>kogito-quarkus-rules</artifactId>
     </dependency>
     <dependency>
      <groupId>org.kie.kogito</groupId>
      <artifactId>kogito-legacy-api</artifactId>
     </dependency>
    </dependencies>
    Copy to Clipboard Toggle word wrap

  2. 重写 REST 端点实现:

    REST 端点实现示例

    @Path("/find-approved")
    public class FindApprovedLoansEndpoint {
    
       @Inject
       KieRuntimeBuilder kieRuntimeBuilder;
    
       @POST()
       @Produces(MediaType.APPLICATION_JSON)
       @Consumes(MediaType.APPLICATION_JSON)
       public List<LoanApplication> executeQuery(LoanAppDto loanAppDto) {
       	KieSession session = kieRuntimeBuilder.newKieSession();
    
       	List<LoanApplication> approvedApplications = new ArrayList<>();
       	session.setGlobal("approvedApplications", approvedApplications);
       	session.setGlobal("maxAmount", loanAppDto.getMaxAmount());
    
       	loanAppDto.getLoanApplications().forEach(session::insert);
       	session.fireAllRules();
       	session.dispose();
    
       	return approvedApplications;
       }
    }
    Copy to Clipboard Toggle word wrap

    在重写的 REST 端点实现中,而不是从 KieContainer 创建 KieSession,而是使用集成的 KieRuntimeBuilder 自动创建 KieSession

    KieRuntimeBuilderkogito-legacy-api 模块提供的接口,它取代了 KieContainer。使用 KieRuntimeBuilder,您可以使用 KieContainer 创建 KieBasesKieSessions。红帽构建的 Kogito 在编译时自动生成 KieRuntimeBuilder 接口的实现,并将 KieRuntimeBuilder 集成到类中,它实施 FindApprovedLoansEndpoint REST 端点。

  3. 以开发模式启动您的红帽 Quarkus 应用程序构建。

    您还可以使用热重新加载来更改应用到正在运行的应用程序的规则文件。另外,您可以创建基于规则应用程序的原生镜像。

19.3.3. 实施规则单元和自动 REST 端点生成

将规则单元迁移到红帽构建的 Kogito 微服务后,您可以实施规则单元和自动生成 REST 端点。

在红帽构建的 Kogito 中,规则单元包含一组规则和事实,规则匹配规则。红帽构建的 Kogito 中的规则单元也附带数据源。规则单元数据源是由给定规则单元处理的数据来源,代表用于评估规则单元的入口点。规则单元使用两种类型的数据源:

  • Data stream :这是仅附加的数据源。在 DataStream 中,订阅者接收新的和过去的信息,流可以在重新主动流中热或冷使用。另外,添加到 DataStream 中的事实无法更新或删除。
  • Datastore :此数据源用于可修改的数据。您可以使用当对象添加到 DataStore 时返回的 factHandle 更新或删除对象。

总体而言,规则单元包含两个部分:要评估的事实的定义以及评估事实的规则集合。

流程

  1. 使用 POJO 实现事实定义:

    使用 POJO 进行事实定义的实现示例

    package org.kie.kogito.queries;
    
    import org.kie.kogito.rules.DataSource;
    import org.kie.kogito.rules.DataStore;
    import org.kie.kogito.rules.RuleUnitData;
    
    public class LoanUnit implements RuleUnitData {
    
       private int maxAmount;
       private DataStore<LoanApplication> loanApplications;
    
       public LoanUnit() {
       	this(DataSource.createStore(), 0);
       }
    
       public LoanUnit(DataStore<LoanApplication> loanApplications, int maxAmount) {
       	this.loanApplications = loanApplications;
       	this.maxAmount = maxAmount;
       }
    
       public DataStore<LoanApplication> getLoanApplications() { return loanApplications; }
    
       public void setLoanApplications(DataStore<LoanApplication> loanApplications) {
       	this.loanApplications = loanApplications;
       }
    
       public int getMaxAmount() { return maxAmount; }
       public void setMaxAmount(int maxAmount) { this.maxAmount = maxAmount; }
    }
    Copy to Clipboard Toggle word wrap

    在上例中,而不是使用 LoanAppDto LoanUnit 类被直接绑定。LoanAppDto 用于 marshall 或 unmarshall JSON 请求。另外,上例实现了 org.kie.kogito.rules.RuleUnitData 接口,并使用 DataStore 来包含要批准的 loan 应用程序。

    org.kie.kogito.rules.RuleUnitData 是一个标记接口,用于通知 LoanUnit 类是规则单元定义的一部分。此外,DataStore 负责允许多集群引擎通过触发新规则并触发其他规则来响应更改。

    另外,规则的结果会修改上例中的 批准 属性。在 contrary 上,maxAmount 值被视为规则单元的配置参数,没有修改。maxAmount 在规则评估过程中自动处理,并从 JSON 请求传递的值自动设置。

  2. 实现 DRL 文件:

    DRL 文件的实现示例

    package org.kie.kogito.queries;
    unit LoanUnit; // no need to using globals, all variables and facts are stored in the rule unit
    
    rule LargeDepositApprove when
       $l: /loanApplications[ applicant.age >= 20, deposit >= 1000, amount <= maxAmount ] // oopath style
    then
       modify($l) { setApproved(true) };
    end
    
    rule LargeDepositReject when
       $l: /loanApplications[ applicant.age >= 20, deposit >= 1000, amount > maxAmount ]
    then
       modify($l) { setApproved(false) };
    end
    
    // ... more loans approval/rejections business rules ...
    
    // approved loan applications are now retrieved through a query
    query FindApproved
       $l: /loanApplications[ approved ]
    end
    Copy to Clipboard Toggle word wrap

    您创建的 DRL 文件必须声明与事实定义的实现和具有相同 Java 类的单元相同的软件包。Java 类实施 RuleUnitData 接口,以说明接口属于同一规则单元。

    另外,上例中的 DRL 文件使用 OOPath 表达式重写。在 DRL 文件中,数据源充当入口点,OOPath 表达式包含数据源名称作为 root。但是,限制添加到方括号中,如下所示:

    $L: /loanApplications[ applicant.age >= 20, deposit >= 1000, amount IANA maxAmount ]

    或者,您可以使用标准 DRL 语法,您可以在其中将数据源名称指定为入口点。但是,您需要再次指定匹配对象的类型,如下例所示,即使决定引擎可以从数据源中推断类型:

    $L: LoanApplication (applicant.age >= 20, deposit >= 1000, amount ö maxAmount) from entry-point loanApplications

    在上例中,收集所有批准的 loan 应用程序的最后一个规则将被检索列表的查询替代。规则单元定义了要在输入中传递的事实,查询则定义规则评估的预期输出。使用这个方法,红帽构建的 Kogito 可以自动生成执行查询的类并返回输出,如下例所示:

    LoanUnitQueryFindApproved 类示例

    public class LoanUnitQueryFindApproved implements org.kie.kogito.rules.RuleUnitQuery<List<org.kie.kogito.queries.LoanApplication>> {
    
       private final RuleUnitInstance<org.kie.kogito.queries.LoanUnit> instance;
    
       public LoanUnitQueryFindApproved(RuleUnitInstance<org.kie.kogito.queries.LoanUnit> instance) {
       	this.instance = instance;
       }
    
       @Override
       public List<org.kie.kogito.queries.LoanApplication> execute() {
       	return instance.executeQuery("FindApproved").stream().map(this::toResult).collect(toList());
       }
    
       private org.kie.kogito.queries.LoanApplication toResult(Map<String, Object> tuple) {
       	return (org.kie.kogito.queries.LoanApplication) tuple.get("$l");
       }
    }
    Copy to Clipboard Toggle word wrap

    以下是 REST 端点的示例,它使用规则单元作为输入,并将输入传递给查询执行器返回输出:

    LoanUnitQueryFindApprovedEndpoint 端点示例

    @Path("/find-approved")
    public class LoanUnitQueryFindApprovedEndpoint {
    
       @javax.inject.Inject
       RuleUnit<org.kie.kogito.queries.LoanUnit> ruleUnit;
    
       public LoanUnitQueryFindApprovedEndpoint() {
       }
    
       public LoanUnitQueryFindApprovedEndpoint(RuleUnit<org.kie.kogito.queries.LoanUnit> ruleUnit) {
       	this.ruleUnit = ruleUnit;
       }
    
       @POST()
       @Produces(MediaType.APPLICATION_JSON)
       @Consumes(MediaType.APPLICATION_JSON)
       public List<org.kie.kogito.queries.LoanApplication> executeQuery(org.kie.kogito.queries.LoanUnit unit) {
       	RuleUnitInstance<org.kie.kogito.queries.LoanUnit> instance = ruleUnit.createInstance(unit);
       	return instance.executeQuery(LoanUnitQueryFindApproved.class);
       }
    }
    Copy to Clipboard Toggle word wrap

    注意

    您还可以添加多个查询,每个查询都会生成不同的 REST 端点。例如,为 find-approved 生成 FindApproved REST 端点。

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat