在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);
}
由于這兩個(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();
更多建議: