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;
   }
}

Applicant 类示例

public class Applicant {

   private String name;
   private int age;

   public Applicant(String name, int age) {
   	this.name = name;
   	this.age = age;
   }
}

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

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

您可以使用红帽构建的 Quarkus 来公开在 Business Central 中通过 REST 端点开发的规则评估。

流程

  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>

  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;
       }
    }

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

    注意

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

    当调用 FindApprovedLoansEndpoint 端点时,会从 KieContainer 创建新的 KieSessionKieSession 将填充 LoanAppDto 中由 JSON 请求未组合生成的对象。

    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;
       }
    }

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

  3. 启动红帽构建的 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

    JSON 响应示例

    [
      {
        "id": "ABC10001",
        "applicant": {
          "name": "John",
          "age": 45
        },
        "amount": 2000,
        "deposit": 1000,
        "approved": true
      }
    ]

注意

使用此方法,您无法使用热重新加载功能,也不能创建项目的原生镜像。在接下来的步骤中,缺少的 Quarkus 功能由 Kogito 扩展提供,该扩展启用了 Quarkus 了解 DRL 文件,并以类似的方式实施热重新加载功能。

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

流程

  1. 将以下依赖项添加到项目 pom.xml 文件中,以启用使用红帽构建的 Quarkus 和旧 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>

  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;
       }
    }

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

    KieRuntimeBuilder 是由替换 KieContainerkogito-legacy-api 模块提供的接口。使用 KieRuntimeBuilder,您可以像在 KieContainer 中创建的方式创建 KieBasesKieSessions。Red Hat build of Kogito 在编译时自动生成 KieRuntimeBuilder 接口的实现,并将 KieRuntimeBuilder 集成到一个类中,它实现了 FindApprovedLoansEndpoint REST 端点。

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

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

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

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

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

  • datastream :这是仅附加数据源。在 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; }
    }

    在上例中,不使用 LoanAppDto the 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

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

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

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

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

    $L: LoanApplication (applicant.age >= 20, deposit >= 1000, amount FULL 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");
       }
    }

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

    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);
       }
    }

    注意

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

Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2026 Red Hat
返回顶部