網上關於easy-rules 介紹的挺多了,以下是一個學習,以及一些學習說明
demo 說明
demo 是一個簡單的用戶實體,同時添加了一些幫助方法,對於規則的定義使用yaml 文件(實際上我們可以基於數據庫,cache,s3文件系統。。。)
包含了,在實際使用中我么如何修改數據以及mvel 的集成使用,以及一些監聽事件的學習
項目准備
- pom.xml
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dalong</groupId>
<artifactId>myruleapps</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<encoding>UTF-8</encoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-mvel</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-spel</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
</project>
- 代碼結構
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── dalong
│ ├── Launcher.java
│ ├── User.java
│ └── UserService.java
└── resources
├── rules.yml
└── simplelogger.properties
代碼說明
- rules.yml
主要是配置了規則,主要是為了學習參數的傳遞(class以及map)同時也包含了如何進行參數的修改以及
關於mvel 的集成使用
rules.yml
---
name: "1"
description: "1"
condition: "user.getAge()>26"
priority: 1
actions:
- "user.age=user.age-2;System.out.println(userinfo);"
---
name: "2"
description: "2"
condition: "user.getAge()<26"
priority: 2
actions:
- "UserService.doAction1(user)"
---
name: "3"
description: "3"
condition: "user.name.length<10"
priority: 3
actions:
- "UserService.doAction2(user)"
---
name: "4"
description: "4"
condition: "user.name.length<40"
priority: 4
actions:
- "System.out.println(\"rule4 \"+userinfo)"
---
name: "5"
description: "5"
condition: "user.name.length<30"
priority: 5
actions:
- "UserService.doAction4(userinfo)"
---
name: "6"
description: "6"
condition: "user.name.length<30"
priority: 6
actions:
- "System.out.println(\"rule6 \"+userinfo)"
---
name: "7"
description: "7"
condition: "user.name.length<30"
priority: 7
actions:
- "UserService.doAction4(user)"
---
name: "8"
description: "8"
condition: "user.name.length<30"
priority: 8
actions:
- "System.out.println(\"rule8 \"+user)"
規則簡單說明:
總共8個, 主要是基於不同的user 實體以及一個userinfo map 類型數據的處理,包含了如何數據修改
UserService 是一個靜態幫助類,主要進行數據操作(更新user以及userinfo 的數據)后邊會有代碼的說明
- Launcher.java
代碼的核心入口
package com.dalong;
import org.jeasy.rules.api.*;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.core.InferenceRulesEngine;
import org.jeasy.rules.core.RuleBuilder;
import org.jeasy.rules.mvel.MVELRuleFactory;
import org.jeasy.rules.support.YamlRuleDefinitionReader;
import org.mvel2.ParserContext;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import static com.dalong.DecreaseTemperatureAction.decreaseTemperature;
import static com.dalong.HighTemperatureCondition.itIsHot;
import static com.dalong.AppendUserName.appendUserName;
import static com.dalong.NameTooShort.nameTooShort;
public class Launcher {
public static void main(String[] args) throws Exception {
app3();
}
private static void app3() throws Exception {
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
ParserContext context =new ParserContext();
context.addImport("UserService", UserService.class);
Rules yamlRules = ruleFactory.createRules(new FileReader(Launcher.class.getClassLoader().getResource("rules.yml").getFile()),context);
DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
Facts facts = new Facts();
Map<String,Object> userinfo = new HashMap<>();
userinfo.put("name2","dalong");
userinfo.put("age2",27);
facts.put("user",new User("dalong",27));
facts.put("userinfo",userinfo);
rulesEngine.registerRuleListener(new MyRulesListener());
rulesEngine.registerRulesEngineListener(new MyRuleEngineListener());
rulesEngine.fire(yamlRules, facts);
}
}
因為是使用了mvel 所以使用了MVELRuleFactory,當前因為我們需要依賴一些幫助類操作數據模型,所以導入了UserService
對於數據的傳遞,我們使用了User 實體模型以及一個map 模型(模擬實際業務場景)
- User.java
用戶實體模型,當然可以作為一個簡單的pojo處理也行
package com.dalong;
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public User(){
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void dosomeThing() throws Exception {
if(this.age<26){
throw new Exception("age is too small");
}
if(this.name.length()<10){
throw new Exception("some wrong");
}
}
public void setAge(int age) {
this.age = age;
}
}
- UserService.java
主要包含了已給幫助操作類,主要是為了mvel使用,定義了一些action,同時為了學習有一個類型處理的
package com.dalong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.HashMap;
import java.util.Map;
public class UserService {
static Log log = LogFactory.getLog(MyRuleEngineListener.class);
public static void doAction1(User user){
log.info("------------do action1------------");
log.info(user.toString());
}
public static void doAction2(User user){
log.info("------------do action2------------");
user.setName("sssssssssssssssssss");
log.info(user.toString());
}
public static void doAction3(Map user){
log.info("------------do action3------------");
log.info(user.toString());
}
public static void doAction4(Object user){
/**
* 基於mvel 修改數據,為了復用doAction4,做了數據兼容處理
*/
if (user instanceof Map ){
log.info("------------do actionn4------------");
((Map)user).put("name2","rule wwwwwwwwwwwwwwwwww");
}
if (user instanceof User) {
((User)user).setName("dalong demo appapapappapa");
}
log.info(user.toString());
}
}
- MyRulesListener.java
rule 運行的監聽,此處我們可以方便進行數據審計記錄(存儲數據庫,同時基於pipline模式,可視化分析任務狀態,以及數據)
package com.dalong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.RuleListener;
public class MyRulesListener implements RuleListener {
Log log = LogFactory.getLog(MyRulesListener.class);
@Override
public boolean beforeEvaluate(Rule rule, Facts facts) {
return true;
}
@Override
public void afterEvaluate(Rule rule, Facts facts, boolean b) {
log.info("-----------------afterEvaluate-----------------");
// log.info(rule.getName()+rule.getDescription()+facts.toString());
}
@Override
public void beforeExecute(Rule rule, Facts facts) {
log.info("-----------------beforeExecute-----------------");
// log.info(rule.getName()+rule.getDescription()+facts.toString());
}
@Override
public void onSuccess(Rule rule, Facts facts) {
log.info("-----------------onSuccess-----------------");
// log.info(rule.getName()+rule.getDescription()+facts.toString());
}
@Override
public void onFailure(Rule rule, Facts facts, Exception e) {
log.info("-----------------onFailure-----------------");
log.info(rule.getName()+"----------"+rule.getDescription()+facts.toString()+e.toString());
}
}
- MyRuleEngineListener.java
記錄引擎的操作日志
package com.dalong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngineListener;
public class MyRuleEngineListener implements RulesEngineListener {
Log log = LogFactory.getLog(MyRuleEngineListener.class);
@Override
public void beforeEvaluate(Rules rules, Facts facts) {
log.info("-----------------beforeEvaluate-----------------");
log.info(rules.toString() +" "+facts.toString());
}
@Override
public void afterExecute(Rules rules, Facts facts) {
log.info("-----------------afterExecute-----------------");
log.info(rules.toString()+" "+facts.toString());
}
}
一些說明
easy-rules 對於數據的傳遞是通過map的,所以mvel使用的時候注意key值的處理,同時還有數據類型的處理,一種
比較好的方式是進行類型判斷(類似上邊的doAction4)
參考資料
https://github.com/j-easy/easy-rules
https://www.theserverside.com/feature/Adding-MVEL-to-the-Java-Developers-Toolkit