EasyRule实战 1简述 2EasyRule的支持环

1.简述

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

  • 轻量级框架和易于学习的API
  • 基于POJO的开发与注解的编程模型
  • 定义抽象的业务规则并轻松应用它们
  • 支持从简单规则创建组合规则的能力
  • 支持使用表达式语言(如MVEL和SpEL)定义规则的能力

2.EasyRule的支持环境

EasyRule支持jdk1.7以上的版本。
maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xml复制代码<!--easy rules核心库-->
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>4.1.0</version>
</dependency>

<!--规则定义文件格式,支持json,yaml等-->
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-support</artifactId>
<version>4.1.0</version>
</dependency>

<!--支持mvel规则语法库-->
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-mvel</artifactId>
<version>4.1.0</version>
</dependency>

3.定义规则引擎

Parameter Type Required Default content
skipOnFirstAppliedRule boolean no MaxInt 告诉引擎在规则失败时跳过后面的规则
skipOnFirstFailedRule boolean no MaxInt 告诉引擎一个规则不会被触发跳过后面的规则
skipOnFirstNonTriggeredRule boolean no MaxInt 告诉引擎一个规则不会被触发跳过后面的规则
rulePriorityThreshold boolean no MaxInt 告诉引擎如果优先级超过定义的阈值,则跳过下一个规则。版本3.3已经不支持更改,默认MaxInt

3.1 rulePriorityThreshold

在创建规则引擎时,我们将其属性 rulePriorityThreshold 的值设置为了 1,这样的设置后的效果相当于在定义的所有规则中将 priority > 1 的规则去掉,换种说法就是只考虑 priority的值小于等于 1 的规则。

3.2 skipOnFirstAppliedRule

所有规则按照优先级从高到低的顺序进行判断,当发现一个满足条件的规则并执行了相关操作后,便不再继续判断其他规则

3.3 skipOnFirstNonTriggeredRule

所有规则按照优先级从高到低的顺序进行判断,如果满足当前的规则,则执行相应的操作,直到遇到不满足条件的规则为止,并且也不会对其他规则进行判断了

1
2
3
4
5
6
scss复制代码RulesEngineParameters parameters = new RulesEngineParameters() 
.rulePriorityThreshold(10)
.skipOnFirstAppliedRule(true)
.skipOnFirstFailedRule(true)
.skipOnFirstNonTriggeredRule(true);
RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

4.定义规则

4.1 使用rule定义

我们将创建一个始终被触发的规则,在执行时将“hello world”打印到控制台。规则如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
typescript复制代码public class RuleClass {

@Rule(priority = 1)
public static class FizzRule {
@Condition
public boolean isFizz(@Fact("number") Integer number) {
return number % 5 == 0;
}

@Action
public void printFizz() {
System.out.print("fizz");
}
}

@Rule(priority = 2)
public static class BuzzRule {
@Condition
public boolean isBuzz(@Fact("number") Integer number) {
return number % 7 == 0;
}

@Action
public void printBuzz() {
System.out.print("buzz");
}
}

public static class FizzBuzzRule extends UnitRuleGroup {

public FizzBuzzRule(Object... rules) {
for (Object rule : rules) {
addRule(rule);
}
}

@Override
public int getPriority() {
return 0;
}
}

@Rule(priority = 3)
public static class NonFizzBuzzRule {

@Condition
public boolean isNotFizzNorBuzz(@Fact("number") Integer number) {
// can return true, because this is the latest rule to trigger according to
// assigned priorities
// and in which case, the number is not fizz nor buzz
return number % 5 != 0 || number % 7 != 0;
}

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

}

@Condition注解标记计算规则条件的方法。此方法必须是公共的,可以有一个或多个用@Fact注解的参数,并返回布尔类型。只有一个方法能用@Condition注解。

@Action注解标记要执行规则操作的方法。规则可以有多个操作。可以使用order属性按指定的顺序执行操作。默认情况下,操作的顺序为0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码
public class RuleClient {
public static void main(String[] args) {
// create a rules engine
RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);
RulesEngine fizzBuzzEngine = new DefaultRulesEngine(parameters);

// create rules
Rules rules = new Rules();
rules.register(new FizzRule());
rules.register(new BuzzRule());
rules.register(new RuleClass.FizzBuzzRule(new RuleClass.FizzRule(), new RuleClass.BuzzRule()));
rules.register(new NonFizzBuzzRule());

// fire rules
Facts facts = new Facts();
for (int i = 1; i <= 100; i++) {
facts.put("number", i);
fizzBuzzEngine.fire(rules, facts);
System.out.println();
}
}

}

4.2 使用RuleBuilder API定义规则

1
2
3
4
5
6
7
8
scss复制代码Rule rule = new RuleBuilder()
.name("myRule")
.description("myRuleDescription")
.priority(3)
.when(condition)
.then(action1)
.then(action2)
.build();

4.3 yml文件定义

规则文件的文件名为 rules.yml ,其内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
yaml复制代码---
name: "three"
description: "print three"
priority: 0
condition: "number % 3 == 0"
actions:
- "System.out.println("three")"

---
name: "five"
description: "print five"
priority: 1
condition: "number % 5 == 0"
actions:
- "System.out.println("five")"

---
name: "seven"
description: "print seven"
priority: 2
condition: "number % 7 == 0"
actions:
- "System.out.println("seven")"

---
name: "itself"
description: "print the number itself otherwise"
priority: 3
condition: "true"
actions:
- "System.out.println(number)"

客户端调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码
public class RuleClient {

public static void main(String[] args) throws FileNotFoundException {
RulesEngine rulesEngine = new DefaultRulesEngine();
Rules rules = MVELRuleFactory.createRulesFrom(new FileReader("rules.yml"));

Facts facts = new Facts();
for (int i = 1; i <= 20; i++) {
System.out.println("====== " + i + " ======");
facts.put("number", i);
rulesEngine.fire(rules, facts);
}
}
}

4.4 MVELRule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
scss复制代码
public class MVELTestRule {

public static void main(String[] args) {

//规则引擎
// RulesEngine rulesEngine = new DefaultRulesEngine();
DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.registerRuleListener(new MyRuleListener());

// ((DefaultRulesEngine) rulesEngine).registerRuleListener(new MyRuleListener());

//规则
MVELRule ageRule = new MVELRule()
.name("my rule")
.description("test demo rule")
.priority(1)
.when("user.age > 18")
.then("map.put('code',200);map.put('msg','success');myResult.setCode('200');myResult.setMsg('success');");

Rules rules = new Rules();
rules.register(ageRule);

Facts facts = new Facts();

User user = new User();
user.setAge(19);
facts.put("user", user);
Map<String, String> map = new HashMap();
MyResult myResult = new MyResult();
facts.put("map", map);
facts.put("myResult", myResult);

rulesEngine.fire(rules, facts);
System.out.println(map);
System.out.println(myResult);

}
}

5.RuleListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
typescript复制代码public class MyRuleListener implements RuleListener {

@Override
public boolean beforeEvaluate(Rule rule, Facts facts) {
return true;
}

@Override
public void afterEvaluate(Rule rule, Facts facts, boolean b) {
System.out.println("---MyRuleListener------afterEvaluate-----");
}

@Override
public void beforeExecute(Rule rule, Facts facts) {
System.out.println("---MyRuleListener------beforeExecute-----");
}

@Override
public void onSuccess(Rule rule, Facts facts) {

System.out.println("---MyRuleListener------onSuccess-----");
}

@Override
public void onFailure(Rule rule, Facts facts, Exception e) {
System.out.println("---MyRuleListener------onFailure-----");
}

}
  • beforeEvaluate 该方法在执行@Condition修饰的方法之前执行。该方法返回false则不执行条件的判断,直接跳过该当前rule。
  • afterEvaluate 该方法在执行@Condition修饰的方法之后执行。
  • beforeExecute 该方法在执行@Action修饰的方法之前执行。
  • onSuccess 该方法在执行@Action修饰的方法之后执行。
  • onFailure 在执行@Action修饰的方法出现异常时,该方法执行。

rulesEngine.fire(rules, facts);之前注册规则监听器

1
scss复制代码  ((DefaultRulesEngine) rulesEngine).registerRuleListener(new MyRuleListener());

6.RulesEngineListener

1
2
3
4
5
6
7
8
9
10
11
typescript复制代码public class MyRulesEngineListener implements RulesEngineListener {
@Override
public void beforeEvaluate(Rules rules, Facts facts) {
System.out.println("---MyRulesEngineListener------beforeEvaluate-----");
}

@Override
public void afterExecute(Rules rules, Facts facts) {
System.out.println("---MyRulesEngineListener------afterExecute-----");
}
}
  • beforeEvaluate 该方法在执行@Action修饰的方法之后执行。在RuleListener之前执行
  • afterExecute 该方法在执行@Condition修饰的方法之前执行。在RuleListener之后执行

rulesEngine.fire(rules, facts);之前注册规则引擎监听器

1
scss复制代码((DefaultRulesEngine) rulesEngine).registerRulesEngineListener(new MyRulesEngineListener());

7.运行规则

1
2
3
4
5
6
7
8
9
10
scss复制代码// create facts
Facts facts = new Facts();

// create rules
Rules rules = new Rules();
rules.register(new HelloWorldRule());

// create a rules engine and fire rules on known facts
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%