天天看點

java 規則引擎執行個體_JAVA規則引擎[Drools]--執行個體篇

随着網際網路應用的飛速發展,各種業務需求也應運而生,對于不斷變更和革新的業務規則而言,項目的開發就很有必要把規則部分獨立提取出來,此時Drools的價值就得到了展現。廢話不多說,看一個簡單的例子。

這裡舉一個手機話費的例子。

一、定義規則:

首先要分析自己的業務邏輯,根據業務而制定出不同的規則,這裡我們假設有3個規則。

1、對于新開戶的手機使用者送20元話費。

2、在2014年10月到12期間充值的使用者,不論金額多少充值滿3次就贈送5元話費。

3、當月充值金額達到100以上,每達到一次贈送話費10元。

二、建立Fact對象:

分析這些規則,并把他們抽象成一個Fact對象。

package com.core.drools;

import java.util.UUID;

public class EntityRule {

private String username;

private boolean account;

private int addtime;

private double currentmoney;

private double totailaddmoney;

public void getSerialnumber(String username,double currentmoney){

System.out.println("Account:"+username+" Balance:¥"+currentmoney);

System.out.println("Serial Number:"+UUID.randomUUID().toString());

}

三、定義規則引擎:

業務和規則都整理清楚了我們就可以開始規則引擎的核心部分啦,這裡我定義的是接口和實作類。

package com.core.drools;

public interface RuleEngine {

public void init();

public void refresh();

public void execute(final EntityRule entityRule);

}

package com.core.drools;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.Reader;

import java.util.ArrayList;

import java.util.List;

import org.drools.RuleBase;

import org.drools.StatefulSession;

import org.drools.compiler.DroolsParserException;

import org.drools.compiler.PackageBuilder;

import org.drools.rule.Package;

import org.drools.spi.Activation;

public class RuleEngineImpl implements RuleEngine{

private RuleBase ruleBase;

@Override

public void init() {

System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");

ruleBase =SingleRuleFactory.getRuleBase();

try {

PackageBuilder backageBuilder = getPackageBuilderFile();

ruleBase.addPackages(backageBuilder.getPackages());

} catch (DroolsParserException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public void refresh() {

ruleBase = SingleRuleFactory.getRuleBase();

Package[] packages = ruleBase.getPackages();

for(Package items :packages){

ruleBase.removePackage(items.getName());

}

init();

}

@Override

public void execute(final EntityRule entityRule) {

if(null == ruleBase.getPackages() || 0 == ruleBase.getPackages().length) {

return;

}

StatefulSession statefulSession = ruleBase.newStatefulSession();

statefulSession.insert(entityRule);

statefulSession.fireAllRules(new org.drools.spi.AgendaFilter() {

public boolean accept(Activation activation) {

return !activation.getRule().getName().contains("_test");

}

});

statefulSession.dispose();

}

private PackageBuilder getPackageBuilderFile()throws Exception {

List drlFilePath = getRuleFile();

List readers = loadRuleFile(drlFilePath);

PackageBuilder backageBuilder = new PackageBuilder();

for (Reader r : readers) {

backageBuilder.addPackageFromDrl(r);

}

if(backageBuilder.hasErrors()) {

throw new Exception(backageBuilder.getErrors().toString());

}

return backageBuilder;

}

private List loadRuleFile(List drlFilePath)

throws FileNotFoundException {

if (null == drlFilePath || 0 == drlFilePath.size()) {

return null;

}

List readers = new ArrayList();

for (String ruleFilePath : drlFilePath) {

readers.add(new FileReader(new File(ruleFilePath)));

}

return readers;

}

private List getRuleFile(){

List drlFilePath = new ArrayList();

String path="D:/utils/my/DroolsProject/src/com/core/drools/drools_rule.drl";

drlFilePath.add(path);

return drlFilePath;

}

}

這裡定義一個單例的RuleBase工廠類。

package com.core.drools;

import org.drools.RuleBase;

import org.drools.RuleBaseFactory;

public class SingleRuleFactory {

private static RuleBase ruleBase;

public static RuleBase getRuleBase(){

return null != ruleBase ? ruleBase : RuleBaseFactory.newRuleBase();

}

}

四、編寫規則檔案:

規則檔案可以根據自己的業務需求定義多個檔案,這裡我隻定義了一個。

package com.core.drools

import com.core.drools.EntityRule;

rule accountEntity

//One

salience 100

lock-on-active true

when

$entityRule : EntityRule(account == true)

then

System.out.println("The new account:Present ¥20.0");

$entityRule.setCurrentmoney($entityRule.getCurrentmoney()+20);

$entityRule.getSerialnumber($entityRule.getUsername(),$entityRule.getCurrentmoney());

System.out.println("--------------------------------------------------");

end

rule billEntity

//two

salience 99

lock-on-active true

date-effective "2014-010-01 00:00:00"

date-expires   "2014-012-31 23:59:59"

when

$entityRule : EntityRule(addtime >= 3)

then

System.out.println("Prepaid phone number reach "+$entityRule.getAddtime()

+" times:Present ¥"+$entityRule.getAddtime()/3*5);

$entityRule.setCurrentmoney($entityRule.getCurrentmoney()+$entityRule.getAddtime()/3*5);

$entityRule.getSerialnumber($entityRule.getUsername(),$entityRule.getCurrentmoney());

System.out.println("--------------------------------------------------");

end

rule addMoney

//Three

salience 98

lock-on-active true

when

$entityRule : EntityRule(totailaddmoney >= 100)

then

System.out.println("The account for the month top-up totail amount is "

+$entityRule.getTotailaddmoney()+":Present ¥"+(int)$entityRule.getTotailaddmoney()/100*10);

$entityRule.setCurrentmoney($entityRule.getCurrentmoney()

+(int)$entityRule.getTotailaddmoney()/100 * 10);

$entityRule.getSerialnumber($entityRule.getUsername(),$entityRule.getCurrentmoney());

end

五、測試引擎:

package com.test;

import java.io.IOException;

import com.core.drools.EntityRule;

import com.core.drools.RuleEngine;

import com.core.drools.RuleEngineImpl;

public class DroolsTest {

public static void main(String[] args) throws IOException {

RuleEngine engineImpl =new RuleEngineImpl();

engineImpl.init();

final EntityRule entityRule= new EntityRule();

entityRule.setCurrentmoney(350d);

entityRule.setUsername("Candy");

entityRule.setAccount(true);

entityRule.setTotailaddmoney(350d);

entityRule.setAddtime(7);

engineImpl.execute(entityRule);

}

}

六、測試結果:

The new account:Present ¥20.0

Account:Candy Balance:¥370.0

Serial Number:0fd98593-caa2-444d-a4ff-b4001cfb3260

------------------------------------------------------------------------------

Prepaid phone number reach 7 times:Present ¥10

Account:Candy Balance:¥380.0

Serial Number:a118b211-c28e-4035-aa60-2f417f62b2f3

------------------------------------------------------------------------------

The account for the month top-up totail amount is 350.0: Present ¥30

Account:Candy Balance:¥410.0

Serial Number:2bfc02c2-267f-47a2-9cda-5a4196e2b7cf