EasyRule概述
Easy-Rules是一款轻量级的规则引擎.
框架特点
-
轻量级类库和容易上手
-
基于POJO的开发与注解的编程模型
-
方便且适用于java的抽象的业务模型规则
-
支持从简单的规则创建组合规则
官方地址: github.com/j-easy/easy…
应用示例
入门示例
定义一个规则,在任何情况下都输出Hello world.
public class HelloRoles {
@Rule(name = "Hello World Rule", description = "Always say hello world")
public static class HelloWorldRule {
@Condition
public boolean when() {
return true;
}
@Action
public void then() throws Exception {
System.out.println("hello world");
}
}
public static void main(String[] args) {
// 创建规则
Rules rules = new Rules();
rules.register(new HelloWorldRule());
// 定义行为
Facts facts = new Facts();
// 将规则应用到行为上
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
执行输出
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
hello world
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Registered rules:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'Hello World Rule', description = 'Always say hello world', priority = '2147483646'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Known facts:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rules evaluation started
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'Hello World Rule' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'Hello World Rule' performed successfully
通过API可以看到我们可以注册多个规则, 多个规则之间处理顺序可以通过设定优先级来定义, 规则优先级的上限值默认是Integer.MAX_VALUE(2147483647). 相同的优先级执行顺序按照规则名称的自然顺序执行.
优先级示例
不同优先级
代码示例
public class WeatherRules {
@Rule(name = "weather rule1", description = "simple rule1", priority = 2)
public static class WeatherRule1 {
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void then() {
System.out.println("It rains, with rule1 .");
}
}
@Rule(name = "weather rule2", description = "simple rule2", priority = 1)
public static class WeatherRule2 {
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void then() {
System.out.println("It rains, with rule2 .");
}
}
public static void main(String[] args) throws Exception{
Rules rules = new Rules();
rules.register(new WeatherRule1());
rules.register(new WeatherRule2());
Facts facts = new Facts();
facts.put("rain", true);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
执行输出
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Registered rules:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule2', description = 'simple rule2', priority = '1'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule1', description = 'simple rule1', priority = '2'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Known facts:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Fact { rain : true }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rules evaluation started
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule2' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule2' performed successfully
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule1' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule1' performed successfully
It rains, with rule2 .
It rains, with rule1 .
通过注册规则可以看到, 注册时是按照优先级注册的, 并不是按照我们代码的顺序注册的. 执行校验输出时也是按照优先级校验然后匹配给出结果. 根据@Condition条件命中来进行对应的规则输出(相同条件可以定制多个规则, 规则命中则执行)
相同优先级
代码示例
public class WeatherRules {
@Rule(name = "weather rule1", description = "simple rule with b", priority = 1)
public static class WeatherRule1 {
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void then() {
System.out.println("It rains, with rule1 .");
}
}
@Rule(name = "weather rule2", description = "simple rule with a", priority = 1)
public static class WeatherRule2 {
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void then() {
System.out.println("It rains, with rule2 .");
}
}
public static void main(String[] args) throws Exception{
Rules rules = new Rules();
rules.register(new WeatherRule2());
rules.register(new WeatherRule1());
Facts facts = new Facts();
facts.put("rain", true);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
执行输出
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Registered rules:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule1', description = 'simple rule with b', priority = '1'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule2', description = 'simple rule with a', priority = '1'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Known facts:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Fact { rain : true }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rules evaluation started
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule1' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule1' performed successfully
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule2' triggered
It rains, with rule1 .
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule2' performed successfully
It rains, with rule2 .
可以看到, 注册顺序在优先级相同的时候是按照规则名称的自然顺序注册, 校验的时候按照注册顺序校验. 这种场景我们也可以通过下面方式实现,同一事件条件绑定多个依赖逻辑.
public class WeatherRules {
@Rule(name = "weather rule Composite", description = "simple rule with order action", priority = 1)
public static class WeatherRuleComposite{
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action(order = 1)
public void then1() {
System.out.println("It rains, with rule1 .");
}
@Action(order = 2)
public void then2() {
System.out.println("It rains, with rule2 .");
}
}
public static void main(String[] args) throws Exception{
Rules rules = new Rules();
rules.register(new WeatherRuleComposite());
Facts facts = new Facts();
facts.put("rain", true);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
执行输出
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Registered rules:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule Composite', description = 'simple rule with order action', priority = '1'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Known facts:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Fact { rain : true }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rules evaluation started
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule Composite' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule Composite' performed successfully
It rains, with rule1 .
It rains, with rule2 .
硬编码示例
上面的示例代码也可以通过硬编码方式实现
public class ApiRules {
public static Rule ruleComposite(){
Rule rule = new RuleBuilder()
.name("weather rule Composite")
.description("simple rule with order action")
.priority(1)
.when(new Condition() {
@Override
public boolean evaluate(Facts facts) {
if((Boolean) facts.get("rain") == true){
return true;
}
return false;
}
})
.then(new Action() {
@Override
public void execute(Facts facts) throws Exception {
if((Boolean) facts.get("rain") == true){
System.out.println("It rains, with rule1 .");
}
}
})
.then(new Action() {
@Override
public void execute(Facts facts) throws Exception {
if((Boolean) facts.get("rain") == true){
System.out.println("It rains, with rule2 .");
}
}
})
.build();
return rule;
}
public static void main(String[] args) throws Exception{
Rules rules = new Rules();
rules.register(ruleComposite());
Facts facts = new Facts();
facts.put("rain", true);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
多规则示例
代码示例
public class WeatherRules {
@Rule(name = "weather rule1", description = "simple rule1", priority = 1)
public static class WeatherRule1 {
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void then() {
System.out.println("It rains, with rule1 .");
}
}
@Rule(name = "weather rule2", description = "simple rule2", priority = 3)
public static class WeatherRule2 {
@Condition
public boolean when(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void then() {
System.out.println("It rains, with rule2 .");
}
}
@Rule(name = "weather rule3", description = "simple rule3", priority = 2)
public static class WeatherRule3 {
@Condition
public boolean when(@Fact("sun") boolean sun) {
return sun;
}
@Action
public void then() {
System.out.println("It sun, with rule3 .");
}
}
public static void main(String[] args) throws Exception{
Rules rules = new Rules();
rules.register(new WeatherRule1());
rules.register(new WeatherRule2());
rules.register(new WeatherRule3());
Facts facts = new Facts();
facts.put("rain", true);
facts.put("sun", true);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
执行输出
It rains, with rule1 .
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
It sun, with rule3 .
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Registered rules:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule1', description = 'simple rule1', priority = '1'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule3', description = 'simple rule3', priority = '2'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rule { name = 'weather rule2', description = 'simple rule2', priority = '3'}
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Known facts:
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Fact { rain : true }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Fact { sun : true }
[main] INFO org.jeasy.rules.core.DefaultRulesEngineListener - Rules evaluation started
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule1' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule1' performed successfully
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule3' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule3' performed successfully
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule2' triggered
[main] INFO org.jeasy.rules.core.DefaultRuleListener - Rule 'weather rule2' performed successfully
It rains, with rule2 .
执行按照规则注册的优先级, 规则1>规则3>规则2, 进行场景条件判断, rain=true时输出rains相关打印、sun=true时输出 sun相关打印.