规则引擎的工作方式有点像if-else,它允许你设置一些条件和动作,然后在程序运行时判断某些动作该不该执行。
如果使用maven,可以直接在pom中加入:
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>4.1.0</version>
</dependency>
如果需要对MVEL, SpEL和JEXL表达式的支持,还需要引入相应的支持包:
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-mvel</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-spel</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-jexl</artifactId>
<version>4.1.0</version>
</dependency>
使用easy-rules非常简单,只需要两个步骤:
以下是一个简单的例子:
public class Test {
public static void main(String[] args) {
// define rules
Rule weatherRule = new RuleBuilder()
.name("weather rule")
.description("if it rains then take an umbrella")
.when(facts -> facts.get("rain").equals(true))
.then(facts -> System.out.println("It rains, take an umbrella!"))
.build();
Rules rules = new Rules();
rules.register(weatherRule);
// define facts
Facts facts = new Facts();
facts.put("rain", true);
// fire rules on known facts
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
例子中的weatherRule是构建的条件和动作,其中“when”里面的是条件,“then”里面的是满足条件后需要执行的动作。 facts是运行中实际的数据。 这个例子会在控制台打印出:It rains, take an umbrella!
Rule用于定义规则和行为,它可以设置以下这些属性:
当when中的表达式返回true时,将执行then中的表达式。 then里面除了可以执行方法外,也可以修改Facts里面的数据。
easy-rules提供了多种定义Rule的写法,还是以上面的例子举例,下面的Rule写法与上面例子中的写法是等价的。
Rule weatherRule = new RuleBuilder()
.name("weather rule")
.description("if it rains then take an umbrella")
.when(facts -> facts.get("rain").equals(true))
.then(facts -> System.out.println("It rains, take an umbrella!"))
.build();
@Rule(name = "weather rule", description = "if it rains then take an umbrella")
public class WeatherRule {
@Condition
public boolean itRains(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void takeAnUmbrella() {
System.out.println("It rains, take an umbrella!");
}
}
Rule weatherRule = new MVELRule()
.name("weather rule")
.description("if it rains then take an umbrella")
.when("rain == true")
.then("System.out.println(\"It rains, take an umbrella!\");");
使用表达式语言需要引入对应的支持包,比如这里使用了MVEL,那么需要在pom中引入easy-rules-mvel这个包
name: "weather rule"
description: "if it rains then take an umbrella"
condition: "rain == true"
actions:
- "System.out.println(\"It rains, take an umbrella!\");"
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
Rule weatherRule = ruleFactory.createRule(new FileReader("weather-rule.yml"));
有时候我们需要把多个规则放在一起使用,就好像写多层if-else一样。 easy-rules为此提供了三个对象来支持复合规则的使用:
下面是使用示范:
//Create a composite rule from two primitive rules
UnitRuleGroup myUnitRuleGroup =
new UnitRuleGroup("myUnitRuleGroup", "unit of myRule1 and myRule2");
myUnitRuleGroup.addRule(myRule1);
myUnitRuleGroup.addRule(myRule2);
//Register the composite rule as a regular rule
Rules rules = new Rules();
rules.register(myUnitRuleGroup);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, someFacts);
Fact是用来装需要判断的数据的,它的API定义如下:
public class Fact<T> {
private final String name;
private final T value;
}
使用的时候直接用Facts,就跟Map用法差不多:
Facts facts = new Facts();
facts.put("foo", "bar");
Rule的“then”代码中可以修改facts的数据,可以使用这个特性来获取返回值。 例如:
Rule ageRule = new MVELRule()
.name("age rule")
.description("Check if person's age is > 18 and marks the person as adult")
.priority(1)
.when("person.age > 18")
.then("person.setAdult(true);");
注意:
Easy Rules 提供了两种RulesEngine接口实现:
DefaultRulesEngine:根据其自然顺序应用规则(默认为优先级)。 InferenceRulesEngine:不断地对已知事实应用规则,直到不再适用规则为止。
DefaultRulesEngine的作用很好理解,就像上面那些例子表现出来的一样。 InferenceRulesEngine则相当于在DefaultRulesEngine的基础上加了一个循环。还是以开头的代码举例,换成InferenceRulesEngine。 这时控制台将重复打印“It rains, take an umbrella!”。
public class Test {
public static void main(String[] args) {
// define rules
Rule weatherRule = new RuleBuilder()
.name("weather rule")
.description("if it rains then take an umbrella")
.when(facts -> facts.get("rain").equals(true))
.then(facts -> System.out.println("It rains, take an umbrella!"))
.build();
Rules rules = new Rules();
rules.register(weatherRule);
// define facts
Facts facts = new Facts();
facts.put("rain", true);
// fire rules on known facts
RulesEngine rulesEngine = new InferenceRulesEngine();
rulesEngine.fire(rules, facts);
}
}
Engine支持以下几个参数配置:
范围 | 类型 | 必需的 | 默认 |
---|---|---|---|
rulePriorityThreshold | int | no | MaxInt |
skipOnFirstAppliedRule | boolean | no | false |
skipOnFirstFailedRule | boolean | no | false |
skipOnFirstNonTriggeredRule | boolean | no | false |
写法如下:
RulesEngineParameters parameters = new RulesEngineParameters()
.rulePriorityThreshold(10)
.skipOnFirstAppliedRule(true)
.skipOnFirstFailedRule(true)
.skipOnFirstNonTriggeredRule(true);
RulesEngine rulesEngine = new DefaultRulesEngine(parameters);
本文由博客一文多发平台 OpenWrite 发布!