当前位置:首页 > 科技  > 软件

四个流行的Java开源规则引擎和入门

来源: 责编: 时间:2023-10-17 10:01:59 237观看
导读在许多业务系统中,会有大量的业务规则配置,而且随着政策制度、业务流程甚至是管理者的决策发生变化,这些业务规则也需要进行更改。这种变化在一些行业特别频繁,并且要求快速响应。规则引擎的作用是为了适应这种变更需求,实

在许多业务系统中,会有大量的业务规则配置,而且随着政策制度、业务流程甚至是管理者的决策发生变化,这些业务规则也需要进行更改。这种变化在一些行业特别频繁,并且要求快速响应。D3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

规则引擎的作用是为了适应这种变更需求,实现业务系统快速且低成本的更新。一般是将业务规则的配置单独拿出来,使之与业务系统保持低耦合,如果这个用于配置的模块做得足够通用且独立,那么它就可以成为一个规则引擎系统。通过规则引擎可以快速响应业务规则的变化。这种方式不需要修改代码,减少了修改业务代码之后出现错误的可能性,如果规则引擎提供前端操作界面,还能够支持业务人员轻松上手配置业务规则。 D3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

本文主要分享一些基于Java的规则引擎,这些规则引擎是目前比较流行的项目,包括:Drolls、Easy RulesRuleBook、OpenL Tablets。并简单介绍这些规则引擎的使用方式。D3u28资讯网——每日最新资讯28at.com

1.Drools

https://www.drools.org/D3u28资讯网——每日最新资讯28at.com

https://github.com/kiegroup/droolsD3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

Drools是一个业务规则管理系统(BRMS)。主要功能模块包括:核心业务规则引擎(BRE)、Web创作和规则管理应用程序(Drools Workbench)、决策模型和符号(DMN)模型以及用于开发的IDE插件(idea、eclipse等)。D3u28资讯网——每日最新资讯28at.com

Drools体系架构如下图所示:D3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

Drools架构的执行步骤如下:D3u28资讯网——每日最新资讯28at.com

  • 将规则加载到规则库中,该规则库始终保持可用。
  • 事实(Facts)被保存到工作内存(Working Memory)中,它们可以被修改或撤回。
  • Pattern Matcher将新的或现有的事实与规则进行匹配, 这个过程称为模式匹配,该过程由规则引擎执行。
  • agenda在冲突解决策略的帮助下管理冲突规则的执行顺序。

D3u28资讯网——每日最新资讯28at.com

以下是SpringBoot的Drools使用例子。D3u28资讯网——每日最新资讯28at.com

(1)定义Pom.xml

创建一个基本的springBoot应用程序,并将drools依赖项添加到pom.xml。D3u28资讯网——每日最新资讯28at.com

<?xml version="1.0" encoding="UTF-8"?><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.6</version>      <relativePath/> <!-- lookup parent from repository -->   </parent>   <groupId>com.praveen.drools.example</groupId>   <artifactId>springboot-drools-demo</artifactId>   <version>0.0.1-SNAPSHOT</version>   <name>springboot-drools-demo</name>   <description>Demo project for Spring Boot with Drools Engine</description>   <properties>      <java.version>11</java.version>      <drools.version>7.67.0.Final</drools.version>      <springfox-swagger2.version>3.0.0</springfox-swagger2.version>   </properties>   <dependencies>      <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-web</artifactId>      </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>      <!-- swagger ui -->      <dependency>         <groupId>io.springfox</groupId>         <artifactId>springfox-boot-starter</artifactId>         <version>${springfox-swagger2.version}</version>      </dependency>      <dependency>         <groupId>io.springfox</groupId>         <artifactId>springfox-swagger-ui</artifactId>         <version>${springfox-swagger2.version}</version>      </dependency>   </dependencies>   <build>      <plugins>         <plugin>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-maven-plugin</artifactId>         </plugin>      </plugins>   </build></project>

D3u28资讯网——每日最新资讯28at.com

(2)创建一个名为DroolsConfig.java的java配置类。

package com.praveen.drools.example.configuration;import com.praveen.drools.example.service.CustomerCategorizeService;import org.kie.api.KieServices;import org.kie.api.builder.KieBuilder;import org.kie.api.builder.KieFileSystem;import org.kie.api.builder.KieModule;import org.kie.api.runtime.KieContainer;import org.kie.internal.io.ResourceFactory;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * Drools Config. * @author Praveen.Nair */@Configurationpublic class DroolsConfig {    private static final String RULES_CUSTOMER_RULES_DRL = "rules/customer-category.drl";    @Bean    public KieContainer kieContainer() {         final KieServices kieServices = KieServices.Factory.get();        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();        kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));        KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);        kb.buildAll();        KieModule kieModule = kb.getKieModule();        return kieServices.newKieContainer(kieModule.getReleaseId());    }}

D3u28资讯网——每日最新资讯28at.com

这个配置类创建一个springbean KieContainer,通过加载应用程序/resources文件夹下的规则文件来构建规则引擎。D3u28资讯网——每日最新资讯28at.com

创建KieFileSystem实例并从应用程序的resources目录加载DRL文件。接着使用KieService和KieBuilder创建KieContainer并将其配置为spring bean。D3u28资讯网——每日最新资讯28at.com

(3)创建模型类

创建名为CustomerRequest的Pojo类和字段。D3u28资讯网——每日最新资讯28at.com

package com.praveen.drools.example.model;import java.util.Objects;import java.util.StringJoiner;/** * Customer request POJO. * @author Praveen.Nair */public final class CustomerRequest {    private final long id;    private final Integer age;    private final String gender;    private final Integer numberOfOrders;    public CustomerRequest(long id, Integer age, String gender, Integer numberOfOrders) {        this.id = id;        this.age = age;        this.gender = gender;        this.numberOfOrders = numberOfOrders;    }    public long getId() {        return id;    }    public Integer getAge() {        return age;    }    public String getGender() {        return gender;    }    public Integer getNumberOfOrders() {        return numberOfOrders;    }    @Override    public boolean equals(Object o) {        if (this == o) {            return true;        }        if (o == null || getClass() != o.getClass()) {            return false;        }        CustomerRequest that = (CustomerRequest) o;        return id == that.id &&                Objects.equals(age, that.age) &&                Objects.equals(gender, that.gender) &&                Objects.equals(numberOfOrders, that.numberOfOrders);    }    @Override    public int hashCode() {        return Objects.hash(id, age, gender, numberOfOrders);    }    @Override    public String toString() {        return new StringJoiner(", ", CustomerRequest.class.getSimpleName() + "[", "]")                .add("id=" + id)                .add("age=" + age)                .add("gender=" + gender)                .add("numberOfOrders='" + numberOfOrders + "'")                .toString();    }}

我们将这个类作为请求对象参数传给规则引擎,并且将字段作为输入发送到定义的规则中,以便为派生customerType。D3u28资讯网——每日最新资讯28at.com

另外,再定义了一个名为CustomerCategory.java的java枚举,用于保存客户类别,规则引擎根据该值派生客户类型。D3u28资讯网——每日最新资讯28at.com

package com.praveen.drools.example.model;/** * Customer Categories. */public enum CustomerCategory {    GENERAL, KIDS, SENIOR_CITIZEN, SUSPENDED;    public String getValue() {        return this.toString();    }}

创建一个名为CustomerType的响应POJO类,如下所示。D3u28资讯网——每日最新资讯28at.com

package com.praveen.drools.example.model;import java.util.Objects;import java.util.StringJoiner;/** * CustomerType Response model. * @author Praveen.Nair */public class CustomerType {    private CustomerCategory customerType;    public CustomerCategory getCustomerType() {        return customerType;    }    public void setCustomerType(CustomerCategory customerType) {        this.customerType = customerType;    }    @Override    public boolean equals(Object o) {        if (this == o) {            return true;        }        if (o == null || getClass() != o.getClass()) {            return false;        }        CustomerType that = (CustomerType) o;        return customerType == that.customerType;    }    @Override    public int hashCode() {        return Objects.hash(customerType);    }    @Override    public String toString() {        return new StringJoiner(", ", CustomerType.class.getSimpleName() + "[", "]")                .add("customerType=" + customerType)                .toString();    }}

(4) 定义Drools规则

创建一个名为customer-category.drl的drools规则文件,并将该文件放在目录/src/main/resources/rules下。D3u28资讯网——每日最新资讯28at.com

import com.praveen.drools.example.model.CustomerRequestimport com.praveen.drools.example.model.CustomerCategory;global com.praveen.drools.example.model.CustomerType customerType;dialect "mvel"rule "Categorize customer based on age"    when        CustomerRequest(age < 20)    then        customerType.setCustomerType(CustomerCategory.KIDS);endrule "Categorize senior citizen customer based on age"    when        CustomerRequest(age > 50)    then      customerType.setCustomerType(CustomerCategory.SENIOR_CITIZEN);endrule "Categorize customer based on number of orders"    when        CustomerRequest(numberOfOrders == 0)    then        customerType.setCustomerType(CustomerCategory.SUSPENDED);endrule "Categorize customer general case"    when        CustomerRequest((gender == "M" || gender == "F") && age > 20 && age < 50)    then        customerType.setCustomerType(CustomerCategory.GENERAL);end

需要在DRL文件中import 使用到的模型。定义一个名为customerType的全局参数,作为多个规则之间共享数据。D3u28资讯网——每日最新资讯28at.com

DRL文件可以包含一个或多个规则。可以使用mvel语法来指定规则。此外,每个规则都可以使用rule关键字进行描述。D3u28资讯网——每日最新资讯28at.com

然后定义when-then语法来指定规则的条件。根据Customer请求的输入值,我们将设置customerType结果。D3u28资讯网——每日最新资讯28at.com

(5) 添加服务层和控制层

创建一个名为CustomerCategorizeService的服务类,并添加以下内容。D3u28资讯网——每日最新资讯28at.com

package com.praveen.drools.example.service;import com.praveen.drools.example.model.CustomerRequest;import com.praveen.drools.example.model.CustomerType;import org.kie.api.runtime.KieContainer;import org.kie.api.runtime.KieSession;/** * Customer Categorization service. * @author Praveen.Nair */public class CustomerCategorizeService {    private final KieContainer kieContainer;    public CustomerCategorizeService(KieContainer kieContainer) {        this.kieContainer = kieContainer;    }    public CustomerType getCustomerType(CustomerRequest customerRequest) {        CustomerType customerType = new CustomerType();        KieSession kieSession = kieContainer.newKieSession();        kieSession.setGlobal("customerType", customerType);        kieSession.insert(customerRequest);        kieSession.fireAllRules();        kieSession.dispose();        return customerType;    }}

使用注入的KieContainer实例创建KieSession实例。返回一个CustomerType类型的全局参数,这个CustomerType将用于保存规则执行结果。D3u28资讯网——每日最新资讯28at.com

使用insert方法将customerRequest传递给DRL文件,然后我们通过调用fireAllRules方法触发所有规则,最后通过调用KieSession的dispose方法终止会话。D3u28资讯网——每日最新资讯28at.com

接着开发一个Controller 将服务发布为一个API: /API/getCustomerType。API的入参为CustomerRequest对象,返回类型为CustomerType。Controller代码如下所示:D3u28资讯网——每日最新资讯28at.com

packagecom.praveen.drools.example.web;import com.praveen.drools.example.model.CustomerRequest;import com.praveen.drools.example.model.CustomerType;import com.praveen.drools.example.service.CustomerCategorizeService;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;@RestController@RequestMapping("/api/getCustomerType")public class CustomerCategorizeController {    private final CustomerCategorizeService customerCategorizeService;    public CustomerCategorizeController(            CustomerCategorizeService customerCategorizeService) {        this.customerCategorizeService = customerCategorizeService;    }    @PostMapping    public ResponseEntity<CustomerType> getCustomer(@RequestBody CustomerRequest customerRequest) {        CustomerType customerType = customerCategorizeService.getCustomerType(customerRequest);        return new ResponseEntity<>(customerType, HttpStatus.OK);    }}

D3u28资讯网——每日最新资讯28at.com

2.Easy Rules

https://github.com/j-easy/easy-rulesD3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

EasyRule是一个轻量级的规则引擎。它提供了用于创建规则的抽象以及规则引擎API,它通过运行一组规则来检测条件并执行操作。D3u28资讯网——每日最新资讯28at.com

以下是EasyRule的一些核心特性:D3u28资讯网——每日最新资讯28at.com

  • 轻量级类库和容易上手
  • 基于POJO的开发与注解的编程模型
  • 基于MVEL表达式的编程模型(适用于极简单的规则,一般不推荐)
  • 支持根据简单的规则创建组合规则
  • 方便且适用于java的抽象的业务模型规则

D3u28资讯网——每日最新资讯28at.com

以下是Java中使用EasyRules的例子:D3u28资讯网——每日最新资讯28at.com

(1)在Maven中引入依赖包

<dependency>    <groupId>org.jeasy</groupId>    <artifactId>easy-rules-core</artifactId>    <version>3.3.0</version></dependency>

D3u28资讯网——每日最新资讯28at.com

(2)定义规则

Easy Rules提供了一些选项来创建规则:D3u28资讯网——每日最新资讯28at.com

  • 声明性注解;
  • API;
  • 表达式语言;
  • 规则描述符。

D3u28资讯网——每日最新资讯28at.com

定义方式如下面Java代码:D3u28资讯网——每日最新资讯28at.com

@Rule(name = "cart total rule", description = "Give 10% off when shopping cart is greater than $200" )public class CartTotalRule {    @Condition    public boolean cartTotal(@Fact("cart") Cart cart) {        return cart.isGreaterThanTwoHundered;    }    @Action    public void giveDiscount(@Fact("cart") Cart cart) {       cart.setTotalDiscount(200);    }}

D3u28资讯网——每日最新资讯28at.com

(3)最后基于事实数据执行规则引擎

public class CartTotalRuleTest {    public static void main(String[] args) {        // define facts        Facts facts = new Facts();        facts.put("cart", get_customer_cart);        // define rules        Rule cartTotalRUle = CartTotalRule        Rules rules = new Rules();        rules.register(cartTotalRUle);        // fire rules on known facts        RulesEngine rulesEngine = new DefaultRulesEngine();        rulesEngine.fire(rules, facts);    }}

D3u28资讯网——每日最新资讯28at.com

3.RuleBook

https://github.com/deliveredtechnologies/rulebookD3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

RuleBook提供了一个简单、灵活并且直观的DSL。RuleBook提供了易于使用的Lambda特定语言或POJO方式来定义规则,Java开发人员可以通过带注解的POJO来组织大规模规则集合,替代那些又臭又长的“if/else”。D3u28资讯网——每日最新资讯28at.com

以下是在Java使用RuleBook的Demo。D3u28资讯网——每日最新资讯28at.com

(1)Maven

<dependency>    <groupId>com.deliveredtechnologies</groupId>    <artifactId>rulebook-core</artifactId>    <version>${version}</version></dependency>

(2)Java定义规则

public class Cart{    private double cartTotal;    private String cartId;    private Customer user;    private List cartEntries;    //getter and setter}public class ShoppingCartRule extends CoRRuleBook {    @Override    public void defineRules() {        //give 10% off when cart total is greater than $200      addRule(RuleBuilder.create().withFactType(Cart.class).withResultType(Double.class)        .when(facts -> facts.getOne().getCartTotal() > 200)        .then((facts, result) -> result.setValue(20))        .stop()        .build());}

D3u28资讯网——每日最新资讯28at.com

(3)执行规则:

public class CartPromotionRule {    public static void main(String[] args) {      RuleBook cartPromotion = RuleBookBuilder.create(ShoppingCartRule.class).withResultType(Double.class)        .withDefaultResult(0.0)        .build();      NameValueReferableMap facts = new FactMap();      facts.setValue("cart", new Cart(450.0, 123456, customer, entries));      cartPromotion.run(facts);    }}

D3u28资讯网——每日最新资讯28at.com

4.OpenL Tablets

http://openl-tablets.org/D3u28资讯网——每日最新资讯28at.com

https://github.com/openl-tablets/openl-tabletsD3u28资讯网——每日最新资讯28at.com

D3u28资讯网——每日最新资讯28at.com

OpenL Tablets 是一个基于 Java和Excel决策表工具的业务规则引擎(BRE)和业务规则管理系统(BRMS)。D3u28资讯网——每日最新资讯28at.com

主要包括以下几个部分:D3u28资讯网——每日最新资讯28at.com

  • Business Rules Engines(业务规则引擎)
  • WebStudio
  • Web services(web服务)
  • Rule repository(基于JCR的实现的规则库)

D3u28资讯网——每日最新资讯28at.com

以下是在Java中使用OpenL Tablets的例子。D3u28资讯网——每日最新资讯28at.com

(1)Maven

<dependency>    <groupId>org.openl</groupId>    <artifactId>org.openl.core</artifactId>    <version>${version}</version></dependency><dependency>    <groupId>org.openl.rules</groupId>    <artifactId>org.openl.rules</artifactId>    <version>${version}</version></dependency>

D3u28资讯网——每日最新资讯28at.com

(2)java实现D3u28资讯网——每日最新资讯28at.com

public class Main {    private CartPromotionRules instance;    public static void main(String[] args) {        Main rules = new Main();        // setup user and case here        rules.process(aCase);    }    public void process(Case aCase) {        EngineFactory engineFactory = new RulesEngineFactory(          getClass().getClassLoader()            .getResource("rules.xls"), CartPromotionRules.class);        instance = engineFactory.newEngineInstance();        instance.executePromotion(aCase, new Response());    }}

本文链接:http://www.28at.com/showinfo-26-13643-0.html四个流行的Java开源规则引擎和入门

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 客服发送一条消息背后的技术和思考

下一篇: 如何将电脑上的“小电影”隐藏为一张图片?这波操作绝了!!

标签:
  • 热门焦点
Top