1. 程式人生 > >Drools的API呼叫

Drools的API呼叫

在上一章節裡,小編簡單的講述了規則檔案的編輯語法與規範,讀者還沒有看過rule的執行過程,下面我們就通過例子對rule進行一下呼叫。在Drools當中,規則的編譯與執行要通過Drools提供的各種API來實現,這些API總體來講可以分為三類:規則編譯規則收集規則的執行

在呼叫時,我們先要做以下幾個操作:

1、Kmodule.xml的編輯

kmodule.xml檔案放到src/main/resources/META-INF/資料夾下


程式碼的實現(具體內容)

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="kbase1" packages="rules.testwrod">
        <ksession name="session"/>
    </kbase>
</kmodule>

分析上面程式碼:

1)   一個kmodule裡面可包含多kbase,這個也是我們這個例子裡面的用例對應drl規則檔案的例子,每一個kbase都有一個name,可以取任意字串,但是不能重名。

2)   然後有一個packages,可以看到packages裡面的字串其實就是src/main/resources下面的資料夾的名稱,或者叫包名,規則引擎會根據這裡定義的包來查詢規則定義檔案。可以同時定義多個包,以逗號分隔開來就行。每一個kbase下面可以包含多個ksession,當然本例中都自定義了一個。注:packages 是以小數點進行分離的,與java中package是一樣的,指的是物理路徑,packages只能指到該值的路徑,是不能遞迴子資料夾的,這一點讀者要謹記。

3)   每一個ksession都有一個name,名字也可以是任意字串,但是也不能重複。kbase和ksession裡面的name屬性是全域性不能重複的。kbase和ksession中其實還有很多其它的屬性,每一個kbase下面可以包含多個ksession。

4)   在執行時,KieContainer會根據*Model物件來建立KieModule、KieBase、KieSession物件。其中KieModule和KieBase只會建立一次,而KieSession則有可能建立多次,因為KieSession的建立成本很低,同時KieSession包含了執行時的資料,所以可以銷燬、建立若干次。

 

2、API的說明,建立一個java檔案

在寫java檔案之前我們先要引用drools相關的jar包,小編再次說明一下,以下的例子都是drools6.4版本

Mavne 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.drools.modules.test</groupId>
  <artifactId>drools-moudles</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>drools-moudles</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- drools 規則引擎 版本 -->
    <drools.version>6.4.0.Final</drools.version>
    <spring.version>4.2.6.RELEASE</spring.version>
    <log4j2.version>2.5</log4j2.version>
  </properties>
  <!-- 依賴項定義 -->
  <dependencies>
    <!-- start drools -->
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-core</artifactId>
      <version>${drools.version}</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-compiler</artifactId>
      <version>${drools.version}</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-decisiontables</artifactId>
      <version>${drools.version}</version>
    </dependency>

    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-workbench-models-guided-template</artifactId>
      <version>${drools.version}</version>
    </dependency>

    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-simulator</artifactId>
      <version>${drools.version}</version>
    </dependency>

    <dependency>
      <groupId>org.jbpm</groupId>
      <artifactId>jbpm-flow-builder</artifactId>
      <version>${drools.version}</version>
    </dependency>

    <dependency>
      <groupId>org.kie</groupId>
      <artifactId>kie-spring</artifactId>
      <version>${drools.version}</version>
    </dependency>

    <dependency>
      <groupId>org.kie</groupId>
      <artifactId>kie-ci</artifactId>
      <version>${drools.version}</version>
    </dependency>
    <dependency>
      <groupId>org.kie</groupId>
      <artifactId>kie-internal</artifactId>
      <version>${drools.version}</version>
    </dependency>
    <dependency>
      <groupId>org.kie</groupId>
      <artifactId>kie-api</artifactId>
      <version>${drools.version}</version>
    </dependency>

    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-workbench-models-guided-dtable</artifactId>
      <version>${drools.version}</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-templates</artifactId>
      <version>${drools.version}</version>
    </dependency>
    <!-- end drools -->
  </dependencies>
    <build>
        <testResources>
            <testResource>
                <directory>
                    ${project.basedir}/src/main/resources
                </directory>
            </testResource>
        </testResources>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
            <source>1.7</source>
            <target>1.7</target>
          </configuration>
        </plugin>
      </plugins>
    </build>
</project>

JAVAcode

package com.drools.test;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class TestWrod{
    public static void main(String[] args) {   
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        KieSession ks =kc.newKieSession("session");
        int count = ks.fireAllRules();
        System.out.println("總執行了"+count+"條規則");
	ks.dispose();
    }
}

分析java程式碼

從classpath中讀取kmodule,建立KieContainder容器。

利用kieContainer物件建立一個新的KieSession,建立session的時候我們傳入了一個name: session”,這個字串很眼熟吧,這個就是我們定義的kmodule.xml檔案中定義的ksession的name。

kieContainer根據kmodule.xml定義的ksession的名稱找到KieSession的定義,然後建立一個KieSession的例項。

KieSession就是一個到規則引擎的連結,通過它就可以跟規則引擎通訊,並且發起執行規則的操作。

然後通過kSession.fireAllRules方法來通知規則引擎執行規則

ks.dispose();最後將kiesession連線關閉

那讓我們看一下結果 如圖2-2


上面只最簡單的helloworld了,是不是很容易就懂了呢,好!那小編再增加一點點難度,我們往規則裡插入一個值,來進行一個簡單的業務判斷。

業務說明:判斷人名是張三,年齡30歲,就將該人名改為李四

實體POJO 

package com.drools.test;

public class Person {
    private String name;
    private int age;
    private String desc;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
   ….此處省略get set 方法,但讀者做例子時一定要加上哦

規則程式碼如下:

Person.drl

package rules.testwrod

import com.drools.test.Person
rule test001
    when
        $p:Person(name=="張三",age==30);
    then
      $p.setName("李四");
      System.out.println("改完後的名字"+$p.getName());
end

在API程式碼說明

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;

public class TestWrod
{

    public static void main(String[] args)
    {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        KieSession ks =kc.newKieSession("session");
        Person person=new Person("張三",30);
        FactHandle insert = ks.insert(person);
        int count = ks.fireAllRules();
        System.out.println("總執行了"+count+"條規則");
        System.out.println(person.getName());
        ks.dispose();
    }
}

那讓我們看一下結果 如圖2-3


                                (圖2-3)

在控制檯上我們可以看到是我們想要的結果。在規則裡變了,java中的Bean也發生了變化,這就滿意了我們業務上的要求?

小編為什麼在最後打了一個問號呢,我們的真的改變了fact物件嘛,是我們真正想要的結果嘛,看起來是沒問題的,控制檯也輸出,但如果我稍稍修改一下業務的話,在之前的業務上新增 並將名為李四的的年齡設定為40,那我規則就應該是這樣了

規則程式碼如下:

Person.drl

package rules.testwrod

import com.drools.test.Person
rule test001
    when
        $p:Person(name=="張三",age==30);
    then
      $p.setName("李四");
      System.out.println("改完後的名字"+$p.getName());
end

rule test002
    when
        $p:Person(name=="李四");
    then
      $p.setAge(40);
      System.out.println("改完後的名字"+$p.getName()+"改完後的年齡"+$p.getAge());
end

java的程式碼不變,執行結果,我們發現結果與第一次相同,難道是我們寫的程式碼沒有編譯?為什麼沒有生效呢,test001規則明明已經將Person中的name屬性改為“李四”了那為什麼值規則test002沒有執行呢,這裡小編就要鄭重的提一句了,這是因為rete的演算法問題,什麼是rete演算法呢,在後面的章節裡小編會做一個詳細的說明,好!,那小編先帶著讀者解決這個問題。其實解決起來很簡單,只要在第一個規則裡新增之前所說的update 就可以了。

將test001規則中的then中 $p.setName("李四");下方新增update($p);再次執行

那讓我們看一下結果 如圖


注:小編是這樣認為的:其實導致這個原因的是因為rete演算法的問題,簡單說明一下,rete演算法會將規則中的內容先全部加載出來,我們在規則中看似把Person的name屬性改變了,但本質中只是引用發生了改變,fact物件是沒有真正改變的。當fact物件發生真正改變時,規則將重新執行,但這樣是有風險的,容易產生死迴圈。解決方案會在rule的屬性中有說明

下面是小編的微信轉帳二維碼,小編再次謝謝讀者的支援,小編會更努力的

----請看下方↓↓↓↓↓↓↓

百度搜索 Drools從入門到精通:可下載開源全套Drools教程

深度Drools教程不段更新中:


更多Drools實戰陸續釋出中………

掃描下方二維碼關注公眾號 ↓↓↓↓↓↓↓↓↓↓