当前位置: 首页>前端>正文

java基于规则设置实现ETL工具 java自带规则引擎

Java规则引擎easy-rules

首先以通俗的语言表达何为规则引擎:
一段代码

public class FizzBuzz {
  public static void main(String[] args) {
    for(int i = 1; i <= 100; i++) {
      if (((i % 5) == 0) && ((i % 7) == 0)){
      	System.out.print("能被5和7同时整除的数字");
      }
      else {
      	System.out.print("i");
      }
    }
  }
}

上述代码中循环了100次,从1开始循环+1.
如果当前数字能被5、7整除。打印:能被5和7同时整除的数字
其余的数字依次打印出来。

其实上面例子中的如果就是我们希望的规则,由此可见当我们业务上遇到较为复杂多样的规则的时候,代码中会出现满篇的if–else。降低代码的易读性、增加代码行数,后期修改规则繁复等等的弊端都体现出来。因此我们用到了规则引擎,也就是今天的主人公——easy-rules

Easy Rules是一个简单但功能强大的Java规则引擎,提供以下特性:

  • 轻量级框架和易于学习的API
  • 基于POJO的开发
  • 支持从原始规则创建组合规则
  • 支持通过表达式(如MVEL,SPEL和JEXL)定义规则

先从一段源码来了解:

package org.jeasy.rules.api;

public interface Rule extends Comparable<Rule> {
	
	private final Condition condition;
    private final List<Action> actions;

	//name:规则命名(空间中的唯一规则名称)
    default String getName() {
        return "rule";
    }
	//规则的简要描述
    default String getDescription() {
        return "description";
    }
	//规则的优先级 1>2>3>4..以此类推
    default int getPriority() {
        return 2147483646;
    }
	/**
    * 此方法封装了规则的条件。
    * @return 如果根据提供的事实可以应用规则,则为true,否则为false
    */
    public boolean evaluate(Facts facts) {
        return this.condition.evaluate(facts);
    }
	/**
    * 此方法封装了规则的操作。
    * @throws 如果在执行操作期间发生错误,则抛出异常
    */
    public void execute(Facts facts) throws Exception {
        Iterator var2 = this.actions.iterator();

        while(var2.hasNext()) {
            Action action = (Action)var2.next();
            action.execute(facts);
        }
    }
}

evaluate()方法封装了必须为true才能触发规则的条件。
execute()方法封装了在满足规则条件时应该执行的操作。
条件和操作由Condition和Action接口表示。
总结来说,我们可以通过定义Condition来判断是否执行此规则,通过Action来决定执行什么样的规则。

上面大概讲述了一下rule的基本结构,下面我们来探讨下究竟如何使用:

注解方式:

完整的示例需要几个东西要讲一下,大家耐心看完:

  • 第一点:Easy Rules提供了@Rule注解,可以将POJO转换为规则
@Rule(name = "myrule", description = "这是一个规则的描述", priority = 1)
public class MyRule {

    // @Condition注解用来标记是否符合规则的方法,这个方法必须是public;
    //可以有一个或多个带@Fact注解的参数,并返回一个boolean类型。
    //只有一个方法可以用@Condition注解标记。
    @Condition
    public boolean when(@Fact("fact") fact) {
        return true;
    }
    
	//@Action注解用来标记执行操作的方法,规则可以有多个操作。可以使用order属性以指定的顺序执行操作
    @Action(order = 1)
    public void then(Facts facts) throws Exception {
        // 规则为true时的操作1
    }

    @Action(order = 2)
    public void finally() throws Exception {
        // 规则为true时的操作2
    }
}

上面代码中,我们自己通过注解的方式先定义了一个规则,以及规则是否执行的条件,执行的内容。

  • 第二点:上面代码中的@Fact注解是什么意思呢?

源码:

public class Fact<T> {
   private final String name;
   private final T value;
}

实际上是一个事实,name代表了在事实中的命名,value则是实际要传递的参数。

java基于规则设置实现ETL工具 java自带规则引擎,java基于规则设置实现ETL工具 java自带规则引擎_规则引擎,第1张

Facts API表示一组事实 所以在同一空间内,fact的name不可重复。

//新建一组事实
Facts facts = new Facts();
facts.put("isFive", "5");
  • 第三点:建立规则引擎
//引擎被创建 默认的应用规则
RulesEngine rulesEngine = new DefaultRulesEngine();
// or 自定义应用规则
RulesEngine rulesEngine = new InferenceRulesEngine();

//执行。 
rulesEngine.fire(rules, facts);

规则引擎参数
Easy Rules引擎可以配置以下参数:

  • rulePriorityThreshold:当优先级超过指定的阈值时,跳过余下的规则。
  • skipOnFirstAppliedRule:当一个规则成功应用时,跳过余下的规则。
  • skipOnFirstFailedRule:当一个规则失败时,跳过余下的规则。
  • skipOnFirstNonTriggeredRule:当一个规则未触发时,跳过余下的规则。

示例:

RulesEngineParameters parameters = new RulesEngineParameters()
    .rulePriorityThreshold(10)
    .skipOnFirstAppliedRule(true)
    .skipOnFirstFailedRule(true)
    .skipOnFirstNonTriggeredRule(true);

RulesEngine rulesEngine = new DefaultRulesEngine(parameters);
简单了解了以上三点,便可以进行一个简单的程序了:

按照我们开篇的例子来说

循环100次,从1开始循环+1.
如果当前数字能被5、7整除。打印:能被5和7同时整除的数字
其余的数字依次打印出来。

把上述规则建立起来 ↓

/**
当前数字能被5、7整除。打印:能被5和7同时整除的数字
**/
@Rule
public class FiveSevenRule {

    @Condition
    public boolean isFiveSevenRule (@Fact("number") Integer number) {
        return number % 5 == 0 && number % 7 == 0;
    }

    @Action
    public void printInput(@Fact("number") Integer number) {
        System.out.print("能被5和7同时整除的数字");
    }

    @Priority
    public int getPriority() {
        return 1;
    }
}
/**
打印其余数字
**/
@Rule
public class OrtherNumRule {

    @Condition
    public boolean isFiveSevenRule (@Fact("number") Integer number) {
        return true;
    }

    @Action
    public void printInput(@Fact("number") Integer number) {
        System.out.print(number);
    }

    @Priority
    public int getPriority() {
        return 2;
    }
}

使用:

public class FizzBuzzWithEasyRules {
    public static void main(String[] args) {
        // 创建规则引擎
        RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);
        RulesEngine fizzBuzzEngine = new DefaultRulesEngine(parameters);

        // 创建规则
        Rules rules = new Rules();
        rules.register(new FiveSevenRule());
        rules.register(new OrtherNumRule());
       

        // 触发规则
        Facts facts = new Facts();
        for (int i = 1; i <= 100; i++) {
            facts.put("number", i);
            fizzBuzzEngine.fire(rules, facts);
        }
    }
}

结果:

java基于规则设置实现ETL工具 java自带规则引擎,java基于规则设置实现ETL工具 java自带规则引擎_后端_02,第2张

由此可见,我们的规则运行起来了。注意:我在创建规则引擎的时候,用了.skipOnFirstAppliedRule(true);也就是说按规则顺序执行后,当规则1完成后,跳过规则2。所以34后面不会再打印35,而直接接了36.

以上便是简单的规则使用。
未完待续…



https://www.xamrdz.com/web/2r71964476.html

相关文章: