13.代碼中調(diào)用規(guī)則

2019-09-19 12:07 更新

13.代碼中調(diào)用規(guī)則

概述

在URule Pro當(dāng)中,是不能直接調(diào)用具體的規(guī)則文件的,我們需要先將定義好的規(guī)則文件放到知識(shí)包中,然后才可以對(duì)規(guī)則文件進(jìn)行測(cè)試和調(diào)用。

在代碼中調(diào)用知識(shí)包,需要先通過(guò)KnowledgeService接口可獲取指定的知識(shí)包ID對(duì)應(yīng)的構(gòu)建好的資源包信息,然后通過(guò)知識(shí)包來(lái)創(chuàng)建具體的KnowledgeSession對(duì)象,接下來(lái)插入相關(guān)業(yè)務(wù)對(duì)象,最后執(zhí)行具體的規(guī)則調(diào)用。

KnowledgeService接口源碼如下:

package com.bstek.urule.runtime.service;
import java.io.IOException;
import com.bstek.urule.runtime.KnowledgePackage;
/**
 * @author Jacky.gao
 * @since 2015年1月28日
 */
public interface KnowledgeService {
    public static final String BEAN_ID="urule.knowledgeService";
    /**
     * 根據(jù)給定的資源包ID獲取對(duì)應(yīng)的KnowledgePackage對(duì)象
     * @param packageId 項(xiàng)目名稱加資源包ID,格式為:projectName/packageId
     * @return 返回與給定的資源包ID獲取對(duì)應(yīng)的KnowledgePackage對(duì)象
     * @throws IOException
     */
    KnowledgePackage getKnowledge(String packageId) throws IOException;
    /**
     * 根據(jù)給定的一個(gè)或多個(gè)資源包ID獲取對(duì)應(yīng)的KnowledgePackage對(duì)象的集合
     * @param packageIds 資源包ID數(shù)組
     * @return 返回與給定的一個(gè)或多個(gè)資源包ID獲取對(duì)應(yīng)的KnowledgePackage對(duì)象集合
     * @throws IOException
     */
    KnowledgePackage[] getKnowledges(String[] packageIds) throws IOException;
}

可以看到,這個(gè)接口中有兩個(gè)方法可供使用,一個(gè)是給一個(gè)知識(shí)包ID(格式為:projectName/packageId)返回一個(gè)對(duì)應(yīng)的KnowledgePackage對(duì)象;另一個(gè)是給一個(gè)或多個(gè)知識(shí)包ID,返回一個(gè)集合類型的KnowledgePackage對(duì)象。在URule Pro當(dāng)中,對(duì)于一個(gè)知識(shí)包,在使用時(shí)引擎會(huì)將其構(gòu)建成KnowledgePackage對(duì)象,在這個(gè)KnowledgePackage對(duì)象中包含了所有由向決策集、決策表、交叉決策表、決策樹、評(píng)分卡、復(fù)雜評(píng)分卡以及決策流等文件構(gòu)建的RuleSet對(duì)象,以及由規(guī)則流構(gòu)成的FlowDefinition對(duì)象。

在使用getKnowledge方法獲取某個(gè)指定的package時(shí),要給一個(gè)資源包ID,需要注意的是資源包的ID在定義要要包含資源包所在項(xiàng)目名稱,格式為:projectName/packageId

通過(guò)KnowledgeService接口獲取到KnowledgePackage對(duì)象后,接下來(lái)就可通過(guò)KnowledgePackage對(duì)象創(chuàng)建com.bstek.urule.runtime.KnowledgeSession對(duì)象,這個(gè)對(duì)象就是引擎提供的與業(yè)務(wù)數(shù)據(jù)交互的接口,通過(guò)這個(gè)接口,可將需要的業(yè)務(wù)數(shù)據(jù)對(duì)象插入到引擎當(dāng)中,最后根據(jù)需要執(zhí)行規(guī)則或規(guī)則流。

package com.bstek.urule.runtime;
import java.util.Map;
import com.bstek.urule.runtime.agenda.AgendaFilter;
/**
 * @author Jacky.gao
 * @since 2015年1月8日
 */
public interface KnowledgeSession extends WorkingMemory{
    /**
     * 執(zhí)行當(dāng)前WorkMemory中所有滿足條件的規(guī)則
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules();
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行過(guò)濾執(zhí)行
     * @param filter 對(duì)滿足條件的規(guī)則進(jìn)行過(guò)濾
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(AgendaFilter filter);
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行過(guò)濾執(zhí)行,并向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param parameters 向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param filter 對(duì)滿足條件的規(guī)則進(jìn)行過(guò)濾
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(Map<String,Object> parameters,AgendaFilter filter);
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行執(zhí)行,并定義執(zhí)行的最大數(shù)目,超出后就不再執(zhí)行
     * @param max 執(zhí)行規(guī)則的最大數(shù)目
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(int max);
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行執(zhí)行,并定義執(zhí)行的最大數(shù)目,超出后就不再執(zhí)行,<br>
     * 并向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param parameters 向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param max 執(zhí)行規(guī)則的最大數(shù)目
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(Map<String,Object> parameters,int max);
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行過(guò)濾執(zhí)行,并定義執(zhí)行數(shù)目的最大值
     * @param filter 對(duì)滿足條件的規(guī)則進(jìn)行過(guò)濾
     * @param max 執(zhí)行規(guī)則的最大數(shù)目
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(AgendaFilter filter,int max);
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行過(guò)濾執(zhí)行,并定義執(zhí)行數(shù)目的最大值,<br>
     * 并向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param parameters 向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param filter 對(duì)滿足條件的規(guī)則進(jìn)行過(guò)濾
     * @param max 執(zhí)行規(guī)則的最大數(shù)目
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(Map<String,Object> parameters,AgendaFilter filter,int max);
    /**
     * 對(duì)當(dāng)前WorkMemory中所有滿足條件的規(guī)則進(jìn)行執(zhí)行,并向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param parameters 向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則執(zhí)行耗時(shí),滿足條件的規(guī)則,執(zhí)行的規(guī)則等信息
     */
    ExecutionResponse fireRules(Map<String,Object> parameters);
    /**
     * 根據(jù)規(guī)則流ID,執(zhí)行目標(biāo)規(guī)則流
     * @param processId 要執(zhí)行的規(guī)則流ID
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則流執(zhí)行耗時(shí)信息
     */
    ExecutionResponse startProcess(String processId);
    /**
     * 根據(jù)規(guī)則流ID,執(zhí)行目標(biāo)規(guī)則流,并向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @param processId 要執(zhí)行的規(guī)則流ID
     * @param parameters 向WorkingMemory中設(shè)置一個(gè)Map的參數(shù)對(duì)象
     * @return 返回一個(gè)ExecutionResponse對(duì)象,其中包含規(guī)則流執(zhí)行耗時(shí)信息
     */
    ExecutionResponse startProcess(String processId,Map<String,Object> parameters);
}

可以看到KnowledgeSession接口擴(kuò)展自WorkingMemory接口,WorkingMemory接口源碼如下:

package com.bstek.urule.runtime;
import java.util.List;
import java.util.Map;


/**
 * @author Jacky.gao
 * @since 2015年1月8日
 */
public interface WorkingMemory {
    /**
     * 插入一個(gè)業(yè)務(wù)數(shù)據(jù)對(duì)象,對(duì)應(yīng)到規(guī)則當(dāng)中就是一個(gè)變量對(duì)象
     * @param fact 目標(biāo)業(yè)務(wù)數(shù)據(jù)對(duì)象
     * @return 插入是否成功
     */
    boolean insert(Object fact);
    /**
     * 利用當(dāng)前WorkingMemory中的規(guī)則信息來(lái)評(píng)估當(dāng)前與業(yè)務(wù)對(duì)象,看其是否會(huì)滿足相關(guān)規(guī)則的條件,同時(shí)將該對(duì)象插入到WorkingMemory
     * @param fact 要評(píng)估的對(duì)象
     */
    void assertFact(Object fact);
    /**
     * 更新一個(gè)在當(dāng)前WorkingMemory中已存在的業(yè)務(wù)對(duì)象,如果對(duì)象存在,那么WorkingMemory會(huì)重新評(píng)估這個(gè)對(duì)象
     * @param fact 要更新的對(duì)象
     * @return 更新是否成功,如果對(duì)象不在WorkingMemory中,則返回false
     */
    boolean update(Object fact);
    /**
     * 移除一個(gè)在WorkingMemory中的對(duì)象,如果對(duì)象存在,那么會(huì)嘗試對(duì)已滿足條件的規(guī)則進(jìn)行重新評(píng)估,
     * 看看當(dāng)前對(duì)象的移除是否會(huì)影響已滿足條件的規(guī)則,如果有影響,則同樣移除已滿足條件的規(guī)則
     * @param obj 要移除的對(duì)象
     * @return 是否移除成功,如果在WorkingMemory中存在,則返回true,否則返回false
     */
    boolean retract(Object obj);
    /**
     * 獲取當(dāng)前WorkingMemory中的某個(gè)參數(shù)值
     * @param key 參數(shù)對(duì)應(yīng)的key值
     * @return 返回具體的值
     */
    Object getParameter(String key);
    /**
     * @return 返回所有的參數(shù)對(duì)象
     */
    Map<String,Object> getParameters();
    /**
     * @return 返回當(dāng)前WorkingMemory中所有的業(yè)務(wù)數(shù)據(jù)對(duì)象
     */
    List<Object> getAllFacts();
    /**
     * @return 返回所有WorkingMemory中所有歷史業(yè)務(wù)數(shù)據(jù)對(duì)象
     */
    List<Object> getHistoryFacts();
}

要通過(guò)KnowledgePackage對(duì)象或這個(gè)對(duì)象的數(shù)組創(chuàng)建一個(gè)KnowledgeSession對(duì)象,可以通過(guò)com.bstek.urule.runtime.KnowledgeSessionFactory類中下面兩個(gè)靜態(tài)方法實(shí)現(xiàn):

/**
 * 創(chuàng)建一個(gè)普通的KnowledgeSession對(duì)象
 * @param knowledgePackage 創(chuàng)建KnowledgeSession對(duì)象所需要的KnowledgePackage對(duì)象
 * @return 返回一個(gè)新的KnowledgeSession對(duì)象
 */
public static KnowledgeSession newKnowledgeSession(KnowledgePackage knowledgePackage){
    return new KnowledgeSessionImpl(knowledgePackage);
}


/**
 * 創(chuàng)建一個(gè)普通的KnowledgeSession對(duì)象
 * @param knowledgePackage 創(chuàng)建KnowledgeSession對(duì)象所需要的KnowledgePackage集合對(duì)象
 * @return 返回一個(gè)新的KnowledgeSession對(duì)象
 */
public static KnowledgeSession newKnowledgeSession(KnowledgePackage[] knowledgePackages){
    return new KnowledgeSessionImpl(knowledgePackages);
}

單次調(diào)用

由于這兩個(gè)方法都是靜態(tài)方法,所以可以直接調(diào)用,下面的代碼中演示了完整的調(diào)用過(guò)程:

package tt;
import rete.test.Dept;
import rete.test.Employee;
import com.bstek.urule.Utils;
import com.bstek.urule.runtime.KnowledgePackage;
import com.bstek.urule.runtime.KnowledgeSession;
import com.bstek.urule.runtime.KnowledgeSessionFactory;
import com.bstek.urule.runtime.service.KnowledgeService;
/**
 * @author Jacky.gao
 * @since 2015年3月5日
 */
public class Invoke {
    public void doTest() throws Exception{
        //從Spring中獲取KnowledgeService接口實(shí)例
        KnowledgeService service=(KnowledgeService)Utils.getApplicationContext().getBean(KnowledgeService.BEAN_ID);
        //通過(guò)KnowledgeService接口獲取指定的資源包"projectName/test123"
        KnowledgePackage knowledgePackage=service.getKnowledge("projectName/test123");
        //通過(guò)取到的KnowledgePackage對(duì)象創(chuàng)建KnowledgeSession對(duì)象
        KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);


        Employee employee=new Employee();
        Dept dept=new Dept();
        dept.setLevel(12);
        employee.setDept(dept);
        employee.setSalary(111000);
        //將業(yè)務(wù)數(shù)據(jù)對(duì)象Employee插入到KnowledgeSession中
        session.insert(employee);
        //執(zhí)行所有滿足條件的規(guī)則
        session.fireRules();
    }
}

在上面的示例當(dāng)中,獲取到KnowledgeSession對(duì)象后,向其中插入一個(gè)名為Employee業(yè)務(wù)數(shù)據(jù)對(duì)象,這樣引擎在計(jì)算時(shí),會(huì)直接采用Employee中相關(guān)數(shù)據(jù),如有條件滿足,同時(shí)有對(duì)Employee中相關(guān)數(shù)據(jù)賦值,那么會(huì)直接反映到當(dāng)前插入的這個(gè)Employee對(duì)象當(dāng)中。

在實(shí)際使用中,可能還會(huì)向KnowledgeSession中添加參數(shù)數(shù)據(jù)(以Map形式添加),對(duì)應(yīng)URule中的參數(shù)庫(kù)文件中定義的信息,引擎計(jì)算完成后,我們要通KnowledgeSession中的getParameter來(lái)獲取具體的參數(shù)對(duì)象,而不 能通過(guò)原添加的Map中獲取,如下代碼:

package tt;
import java.util.HashMap;
import java.util.Map;
import rete.test.Dept;
import rete.test.Employee;
import com.bstek.urule.Utils;
import com.bstek.urule.runtime.KnowledgePackage;
import com.bstek.urule.runtime.KnowledgeSession;
import com.bstek.urule.runtime.KnowledgeSessionFactory;
import com.bstek.urule.runtime.service.KnowledgeService;
/**
 * @author Jacky.gao
 * @since 2015年3月5日
 */
public class Invoke {
    public void doTest() throws Exception{
        //從Spring中獲取KnowledgeService接口實(shí)例
        KnowledgeService service=(KnowledgeService)Utils.getApplicationContext().getBean(KnowledgeService.BEAN_ID);
        //通過(guò)KnowledgeService接口獲取指定的資源包"test123"
        KnowledgePackage knowledgePackage=service.getKnowledge("projectName/test123");
        //通過(guò)取到的KnowledgePackage對(duì)象創(chuàng)建KnowledgeSession對(duì)象
        KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);


        Employee employee=new Employee();
        Dept dept=new Dept();
        dept.setLevel(12);
        employee.setDept(dept);
        employee.setSalary(111000);
        //將業(yè)務(wù)數(shù)據(jù)對(duì)象Employee插入到KnowledgeSession中
        session.insert(employee);
        //執(zhí)行所有滿足條件的規(guī)則


        Map<String,Object> parameter=new HashMap<String,Object>();
        parameter.put("count", 10);
        parameter.put("result", true);
        //觸發(fā)規(guī)則時(shí)并設(shè)置參數(shù)
        session.fireRules(parameter);


        //獲取計(jì)算后的result值,要通過(guò)KnowledgeSession,而不能通過(guò)原來(lái)的parameter對(duì)象
        boolean result=(Boolean)session.getParameter("result");
        System.out.println(result);
    }
}

從上面的代碼中可以看到,在規(guī)則計(jì)算完成后,在獲取計(jì)算后的參數(shù)中的result值時(shí),我們并沒(méi)有用提供參數(shù)的parameter,而是通過(guò)KnowledgeSession的getParameter來(lái)實(shí)現(xiàn),這是因?yàn)樵谙騅nowledgeSession設(shè)置參數(shù)時(shí),引擎會(huì)將參數(shù)中所有的值取出并放入到引擎中內(nèi)置的一個(gè)Map中,以避免影響原參數(shù)的值。所以計(jì)算完成后,我們要通過(guò)KnowledgeSession的getParameter來(lái)獲取計(jì)算后的參數(shù)值。

如果我們的資源包中包含有規(guī)則流,那么在插入好相關(guān)業(yè)務(wù)數(shù)據(jù)對(duì)象后,可以通過(guò)KnowledgeSession中提供的startProcess來(lái)實(shí)現(xiàn)規(guī)則流的調(diào)用,如下面的代碼所示:

package tt;
import java.util.HashMap;
import java.util.Map;
import rete.test.Dept;
import rete.test.Employee;
import com.bstek.urule.Utils;
import com.bstek.urule.runtime.KnowledgePackage;
import com.bstek.urule.runtime.KnowledgeSession;
import com.bstek.urule.runtime.KnowledgeSessionFactory;
import com.bstek.urule.runtime.service.KnowledgeService;
/**
 * @author Jacky.gao
 * @since 2015年3月5日
 */
public class Invoke {
    public void doTest() throws Exception{
        //從Spring中獲取KnowledgeService接口實(shí)例
        KnowledgeService service=(KnowledgeService)Utils.getApplicationContext().getBean(KnowledgeService.BEAN_ID);
        //通過(guò)KnowledgeService接口獲取指定的資源包"test123"
        KnowledgePackage knowledgePackage=service.getKnowledge("projectName/test123");
        //通過(guò)取到的KnowledgePackage對(duì)象創(chuàng)建KnowledgeSession對(duì)象
        KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);


        Employee employee=new Employee();
        Dept dept=new Dept();
        dept.setLevel(12);
        employee.setDept(dept);
        employee.setSalary(111000);
        //將業(yè)務(wù)數(shù)據(jù)對(duì)象Employee插入到KnowledgeSession中
        session.insert(employee);
        //執(zhí)行所有滿足條件的規(guī)則


        Map<String,Object> parameter=new HashMap<String,Object>();
        parameter.put("count", 10);
        parameter.put("result", true);


        //開始規(guī)則流并設(shè)置參數(shù)
        session.startProcess("flow-test",parameter);


        //獲取計(jì)算后的result值,要通過(guò)KnowledgeSession,而不能通過(guò)原來(lái)的parameter對(duì)象
        boolean result=(Boolean)session.getParameter("result");
        System.out.println(result);
    }
}

在URule Pro當(dāng)中,規(guī)則流中是不存在人工任務(wù)的,也就是說(shuō)規(guī)則流的執(zhí)行是一次性完成的,這點(diǎn)與包含人工任務(wù)的工作流引擎不同,比如UFLO,在UFLO中有人工任務(wù),所以開啟流程實(shí)例后可能需要多次完成人工任務(wù)才能完成一個(gè)流程實(shí)例。

批處理支持

實(shí)際業(yè)務(wù)當(dāng)中,我們除了會(huì)做單條規(guī)則計(jì)算外,還有可能需要運(yùn)行規(guī)則引擎來(lái)處理一大批數(shù)據(jù),這些數(shù)據(jù)可能有幾萬(wàn)條,幾十萬(wàn)條,甚至更多。在這種情況下,如果我們還是采用普通的KnowledgeSession在一個(gè)線程里處理大批量數(shù)據(jù)的話,那么引擎還是只能在當(dāng)前線程里運(yùn)行,這樣就會(huì)需要很長(zhǎng)的時(shí)間才能可能將這幾十萬(wàn)條甚至更多的數(shù)據(jù)處理完成,在這個(gè)時(shí)候,為了充分利用服務(wù)器較強(qiáng)的CPU性能,我們可以使用BatchSession利用多線程并行處理這些數(shù)據(jù)。顧名思義BatchSession是用來(lái)做批處理任務(wù)的會(huì)話對(duì)象,它是 URule Pro當(dāng)中提供的多線程并行處理大批量業(yè)務(wù)數(shù)據(jù)的規(guī)則會(huì)話對(duì)象。

要得到一個(gè)BatchSession對(duì)象,我們也需要提供一個(gè)或多個(gè)KnowledgePackage對(duì)象,獲取KnowledgePackage對(duì)象的方法與上面介紹的方法相同,有了KnowledgePackage對(duì)象后,就可以利用KnowledgeSessionFactory類創(chuàng)建一個(gè)BatchSession對(duì)象。

在com.bstek.urule.runtime.KnowledgeSessionFactory類中除上面提到的兩個(gè)構(gòu)建KnowledgeSession的靜態(tài)方法外,還提供了另外八個(gè)可用于構(gòu)建BatchSession的靜態(tài)方法,其源碼如下:

/**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,這里默認(rèn)將開啟10個(gè)普通的線程池來(lái)運(yùn)行提交的批處理任務(wù),默認(rèn)將每100個(gè)任務(wù)放在一個(gè)線程里處理
     * @param knowledgePackage 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage對(duì)象
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSession(KnowledgePackage knowledgePackage){
        return new BatchSessionImpl(knowledgePackage,BatchSession.DEFAULT_THREAD_SIZE,BatchSession.DEFAULT_BATCH_SIZE);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,第二個(gè)參數(shù)來(lái)指定線程池中可用線程個(gè)數(shù),默認(rèn)將每100個(gè)任務(wù)放在一個(gè)線程里處理
     * @param knowledgePackage 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage對(duì)象
     * @param threadSize 線程池中可用的線程個(gè)數(shù)
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSessionByThreadSize(KnowledgePackage knowledgePackage,int threadSize){
        return new BatchSessionImpl(knowledgePackage,threadSize,BatchSession.DEFAULT_BATCH_SIZE);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,這里默認(rèn)將開啟10個(gè)普通的線程池來(lái)運(yùn)行提交的批處理任務(wù),第二個(gè)參數(shù)用來(lái)決定單個(gè)線程處理的任務(wù)數(shù)
     * @param knowledgePackage 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage對(duì)象
     * @param batchSize 單個(gè)線程處理的任務(wù)數(shù)
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSessionByBatchSize(KnowledgePackage knowledgePackage,int batchSize){
        return new BatchSessionImpl(knowledgePackage,BatchSession.DEFAULT_THREAD_SIZE,batchSize);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,第二個(gè)參數(shù)來(lái)指定線程池中可用線程個(gè)數(shù),第三個(gè)參數(shù)用來(lái)決定單個(gè)線程處理的任務(wù)數(shù)
     * @param knowledgePackage 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage對(duì)象
     * @param threadSize 線程池中可用的線程個(gè)數(shù)
     * @param batchSize 單個(gè)線程處理的任務(wù)數(shù)
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSession(KnowledgePackage knowledgePackage,int threadSize,int batchSize){
        return new BatchSessionImpl(knowledgePackage,threadSize,batchSize);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,這里默認(rèn)將開啟10個(gè)普通的線程池來(lái)運(yùn)行提交的批處理任務(wù),默認(rèn)將每100個(gè)任務(wù)放在一個(gè)線程里處理
     * @param knowledgePackage 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage集合對(duì)象
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSession(KnowledgePackage[] knowledgePackages){
        return new BatchSessionImpl(knowledgePackages,BatchSession.DEFAULT_THREAD_SIZE,BatchSession.DEFAULT_BATCH_SIZE);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,第二個(gè)參數(shù)來(lái)指定線程池中可用線程個(gè)數(shù),默認(rèn)將每100個(gè)任務(wù)放在一個(gè)線程里處理
     * @param knowledgePackages 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage集合對(duì)象
     * @param threadSize 線程池中可用的線程個(gè)數(shù)
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSessionByThreadSize(KnowledgePackage[] knowledgePackages,int threadSize){
        return new BatchSessionImpl(knowledgePackages,threadSize,BatchSession.DEFAULT_BATCH_SIZE);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,這里默認(rèn)將開啟10個(gè)普通的線程池來(lái)運(yùn)行提交的批處理任務(wù),第二個(gè)參數(shù)用來(lái)決定單個(gè)線程處理的任務(wù)數(shù)
     * @param knowledgePackages 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage集合對(duì)象
     * @param batchSize 單個(gè)線程處理的任務(wù)數(shù)
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSessionByBatchSize(KnowledgePackage[] knowledgePackages,int batchSize){
        return new BatchSessionImpl(knowledgePackages,BatchSession.DEFAULT_THREAD_SIZE,batchSize);
    }


    /**
     * 創(chuàng)建一個(gè)用于批處理的BatchSession對(duì)象,第二個(gè)參數(shù)來(lái)指定線程池中可用線程個(gè)數(shù),第三個(gè)參數(shù)用來(lái)決定單個(gè)線程處理的任務(wù)數(shù)
     * @param knowledgePackages 創(chuàng)建BatchSession對(duì)象所需要的KnowledgePackage集合對(duì)象
     * @param threadSize 線程池中可用的線程個(gè)數(shù)
     * @param batchSize 單個(gè)線程處理的任務(wù)數(shù)
     * @return 返回一個(gè)新的BatchSession對(duì)象
     */
    public static BatchSession newBatchSession(KnowledgePackage[] knowledgePackages,int threadSize,int batchSize){
        return new BatchSessionImpl(knowledgePackages,threadSize,batchSize);
    }

前面介紹規(guī)則流中的決策節(jié)點(diǎn)時(shí),了解到?jīng)Q策節(jié)點(diǎn)中支持百分比分流,這種百分比分流就要求必須是在使用BatchSession處理一批數(shù)據(jù)的時(shí)候,或者是一個(gè)用一個(gè)普通的KnowledgeSession一次性處理多條數(shù)據(jù)才有效,否則規(guī)則流只會(huì)走比例最高的那個(gè)分支。

BatchSession接口比較簡(jiǎn)單,它只定義了兩個(gè)方法:

/**
     * 添加一個(gè)具體要執(zhí)行Business對(duì)象
     * @param business Business對(duì)象實(shí)例
     */
    void addBusiness(Business business);




    /**
     * 等待線程池中所有業(yè)務(wù)線程執(zhí)行完成,在進(jìn)行批處理操作時(shí)一定要以此方法作為方法調(diào)用結(jié)尾
     */
    void waitForCompletion();

可以看到,它可以接收若干個(gè)名為com.bstek.urule.runtime.Business接口實(shí)例,Business接口比較簡(jiǎn)單,它只有一個(gè)方法:

package com.bstek.urule.runtime;
/**
 * @author Jacky.gao
 * @since 2015年9月29日
 */
public interface Business {
    void execute(KnowledgeSession session);
}

在Business實(shí)現(xiàn)類中,我們的業(yè)務(wù)寫在execute方法當(dāng)中,在這個(gè)方法中,只有一個(gè)KnowledgeSession對(duì)象,這個(gè)session對(duì)象就是我們與規(guī)則引擎操作的對(duì)象,示例代碼如下:

//從Spring中獲取KnowledgeService接口實(shí)例
KnowledgeService service=(KnowledgeService)Utils.getApplicationContext().getBean(KnowledgeService.BEAN_ID);
//通過(guò)KnowledgeService接口獲取指定的資源包"aaa"
KnowledgePackage knowledgePackage=service.getKnowledge("projectName/aaa");


//通過(guò)取的KnowledgePackage對(duì)象創(chuàng)建BatchSession對(duì)象,在這個(gè)對(duì)象中,我們將開啟5個(gè)線程,每個(gè)線程最多放置10個(gè)Bussiness接口實(shí)例運(yùn)行
BatchSession batchSession=KnowledgeSessionFactory.newBatchSession(knowledgePackage, 5, 10);


for(int i=0;i<100;i++){
    batchSession.addBusiness(new Business(){
        @Override
        public void execute(KnowledgeSession session) {
            Employee employee=new Employee();
            employee.setSalary(11080);
            //將業(yè)務(wù)數(shù)據(jù)對(duì)象Employee插入到KnowledgeSession中
            session.insert(employee);
            session.startProcess("demo");
        }
    });
}
//等待所有的線程執(zhí)行完成,對(duì)于BatchSession調(diào)用來(lái)說(shuō),此行代碼必不可少,否則將導(dǎo)致錯(cuò)誤
batchSession.waitForCompletion();
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)