別再說你不會,規則引擎Drools了

一、爲什麼要使用規則引擎

 有一天運營想弄一個積分策略,計算額外積分金額 ,規則如下:

訂單原價金額 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 集成、熱加載》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章