一、爲什麼要使用規則引擎
有一天運營想弄一個積分策略,計算額外積分金額 ,規則如下:
訂單原價金額 100以下, 不加分;
100-500 加100分;
500-1000 加500分;
1000 以上 加1000分;
傳統java業務實現如下:
public class JavaScoreExample {
public static void main(String[] args) throws Exception {
List<Order> orderList = getInitData();
for (int i=0; i<orderList.size(); i++){
Order order = orderList.get(i);
if (order.getAmout() <= 100){
order.setScore(0);
addScore(order);
}else if(order.getAmout() > 100 && order.getAmout() <= 500){
order.setScore(100);
addScore(order);
}else if(order.getAmout() > 500 && order.getAmout() <= 1000){
order.setScore(500);
addScore(order);
}else{
order.setScore(1000);
addScore(order);
}
}
}
private static void addScore(Order o){
System.out.println("用戶" + o.getUser().getName() + "享受額外增加積分: " + o.getScore());
}
private static List<Order> getInitData() throws Exception {
List<Order> orderList = new ArrayList<Order>();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
{
Order order = new Order();
order.setAmout(80);
order.setBookingDate(df.parse("2015-07-01"));
User user = new User();
user.setLevel(1);
user.setName("Name1");
order.setUser(user);
orderList.add(order);
}
{
Order order = new Order();
order.setAmout(200);
order.setBookingDate(df.parse("2015-07-02"));
User user = new User();
user.setLevel(2);
user.setName("Name2");
order.setUser(user);
orderList.add(order);
}
return orderList;
}
}
這時候由於市場需求變化,又要調整規則時候,則又要進行業務層面的代碼修改、部署,十分麻煩。
如果我們可以把決策規則從應用程序中分離出來,將對系統提供很大的便利!
由此,誕生了規則引擎!如下如所示:
規則引擎優勢:
對系統的使用人員
把業務策略(規則)的創建、修改和維護的權利交給業務經理
提高業務靈活性
加強業務處理的透明度,業務規則可以被管理
減少對IT人員的依賴程度
避免將來升級的風險
對IT開發人員
簡化系統架構,優化應用
提高系統的可維護性和維護成本
方便系統的整合
減少編寫“硬代碼”業務規則的成本和風險
目前市面上比較熱門的規則引擎有幾款:
Ilog JRules 是最有名的商用BRMS;
Drools 是最活躍的開源規則引擎;
Jess 是Clips的java實現,就如JRuby之於Ruby,是AI系的代表;
Visual Rules(旗正規則引擎)國內商業規則引擎品牌。
本文將着重介紹Drools。
二、什麼是Drools
Drools 是一個基於Charles Forgy’s的RETE算法的,易於訪問企業策略、易於調整以及易於管理的開源業務規則引擎,符合業內標準,速度快、效率高。
業務分析師人員或審覈人員可以利用它輕鬆查看業務規則,從而檢驗是否已編碼的規則執行了所需的業務規則。
Drools 是用Java語言編寫的開放源碼規則引擎,使用Rete算法對所編寫的規則求值。Drools允許使用聲明方式表達業務邏輯。可以使用非XML的本地語言編寫規則,從而便於學習和理解。並且,還可以將Java代碼直接嵌入到規則文件中,這令Drools的學習更加吸引人。
三、Drools 實戰
下面我們將使用drools 把一部分中計算額外積分金額 規則從代碼中剝離出來:
github 傳送門:https://github.com/vincent9309/drools:
1、引入pom文件
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.0.0.Final</version>
</dependency>
2、 在src/main/resources/ruls 新建Point-rules.drl規則文件:
package rules
import com.neo.drools.entity.Order
rule "zero"
no-loop true
lock-on-active true
salience 1
when
$s : Order(amout <= 100)
then
$s.setScore(0);
update($s);
end
rule "add100"
no-loop true
lock-on-active true
salience 1
when
$s : Order(amout > 100 && amout <= 500)
then
$s.setScore(100);
update($s);
end
rule "add500"
no-loop true
lock-on-active true
salience 1
when
$s : Order(amout > 500 && amout <= 1000)
then
$s.setScore(500);
update($s);
end
rule "add1000"
no-loop true
lock-on-active true
salience 1
when
$s : Order(amout > 1000)
then
$s.setScore(1000);
update($s);
end
3、src/main/resources/META-INF新建配置文件kmodule.xml:
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="point-rulesKB" packages="rules">
<ksession name="point-rulesKS"/>
</kbase>
<kbase name="HelloWorldKB" packages="rules">
<ksession name="HelloWorldKS"/>
</kbase>
</kmodule>
4、最後在程序中調用規則,即可實現:
/**
* 計算額外積分金額 規則如下: 訂單原價金額
* 100以下, 不加分
* 100-500 加100分
* 500-1000 加500分
* 1000 以上 加1000分
*
* @param args
* @throws Exception
*/
public static final void main(final String[] args) throws Exception{
// KieServices is the factory for all KIE services
KieServices ks = KieServices.Factory.get();
// From the kie services, a container is created from the classpath
KieContainer kc = ks.getKieClasspathContainer();
execute( kc );
}
public static void execute( KieContainer kc ) throws Exception{
// From the container, a session is created based on
// its definition and configuration in the META-INF/kmodule.xml file
KieSession ksession = kc.newKieSession("point-rulesKS");
List<Order> orderList = getInitData();
for (int i = 0; i < orderList.size(); i++) {
Order o = orderList.get(i);
ksession.insert(o);
ksession.fireAllRules();
// 執行完規則後, 執行相關的邏輯
addScore(o);
}
ksession.dispose();
}
private static void addScore(Order o){
System.out.println("用戶" + o.getUser().getName() + "享受額外增加積分: " + o.getScore());
}
private static List<Order> getInitData() throws Exception {
List<Order> orderList = new ArrayList<Order>();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
{
Order order = new Order();
order.setAmout(80);
order.setBookingDate(df.parse("2015-07-01"));
User user = new User();
user.setLevel(1);
user.setName("Name1");
order.setUser(user);
order.setScore(111);
orderList.add(order);
}
{
Order order = new Order();
order.setAmout(200);
order.setBookingDate(df.parse("2015-07-02"));
User user = new User();
user.setLevel(2);
user.setName("Name2");
order.setUser(user);
orderList.add(order);
}
return orderList;
}
結果輸出:
總結:
應用場景
· 爲提高效率,管理流程必須自動化,儘管現代商業規則異常複雜。
· 市場要求業務規則經常變化,系統必須依據業務規則的變化快速、低成本的更新。
· 爲了快速、低成本的更新,業務人員應能直接管系統中的規則,不需要程序開發人員參與。
作用與優點:
· 將業務規則與業務系統分離,解耦合;
· 實現自然語言描述規則邏輯,業務人員易於理解;
· 可視化的規則定製、審批、查詢及管理;
· 能有效的提高實現複雜邏輯的代碼的可維護性;
· 應付特殊狀況,即客戶一開始沒有提到要將業務邏輯考慮在內;
· 符合組織對敏捷或迭代開發過程的使用;
下文將繼續講解,drools基礎語法,以及使用springboot 集成drools企業級開發,並實現熱加載規則!
傳送門:《規則引擎Drools 之 springboot 集成、熱加載》