文档章节

JAVA规则引擎[Drools]--实例篇

Candy_Desire
 Candy_Desire
发布于 2014/11/07 16:32
字数 995
阅读 3865
收藏 29

随着互联网应用的飞速发展,各种业务需求也应运而生,对于不断变更和革新的业务规则而言,项目的开发就很有必要把规则部分独立提取出来,此时Drools的价值就得到了体现。废话不多说,看一个简单的例子。

这里举一个手机话费的例子。

一、定义规则:

首先要分析自己的业务逻辑,根据业务而制定出不同的规则,这里我们假设有3个规则。

1、对于新开户的手机用户送20元话费。

2、在2014年10月到12期间充值的用户,不论金额多少充值满3次就赠送5元话费。

3、当月充值金额达到100以上,每达到一次赠送话费10元。

二、创建Fact对象:

分析这些规则,并把他们抽象成一个Fact对象。

package com.core.drools;

import java.util.UUID;

/**
 * EntityRule-Model
 * @author Candy
 *
 */
public class EntityRule {
	
	private String username;
	
	/** Whether for new account. */
	private boolean account;
	
	/** The number of add. */
	private int addtime;
	
	/** The sum of the current account. */
	private double currentmoney;
	
	/** The totail amount added. */
	private double totailaddmoney;
	
	/**
	 * Record the serial number of the operation.
	 * @param username
	 * @param currentmoney
	 */
	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;

/**
 * RuleEngine-Interface
 * @author Candy
 * 
 */
public interface RuleEngine {
	
	/**
	 * Initializes the rules engine.
	 */
	public void init();
	
	/**
	 *  Refresh the rules engine.
	 */
	public void refresh();
	
	/**
	 * Execute the rules engine.
	 */
	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;

/**
 * RuleEngine-Implements
 * @author Candy
 *
 */
public class RuleEngineImpl implements RuleEngine{
	
	private RuleBase ruleBase;
	
     /*
     * (non-Javadoc)
     * @see com.core.drools.RuleEngine#init()
     */
	@Override
	public void init() {
		/** Sets the system time format. */
		System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
		/** Get the base factory. */
		ruleBase =SingleRuleFactory.getRuleBase();
		try {
			/** Get the rule files has bean read. */
			PackageBuilder backageBuilder = getPackageBuilderFile();
			/** Add the package to the 'RuleBase'. */
			ruleBase.addPackages(backageBuilder.getPackages());
		} catch (DroolsParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
     /*
     * (non-Javadoc)
     * @see com.core.drools.RuleEngine#refresh()
     */
	@Override
	public void refresh() {
		ruleBase = SingleRuleFactory.getRuleBase();
		Package[] packages = ruleBase.getPackages();
		for(Package items :packages){
			ruleBase.removePackage(items.getName());
		}
		init();
	}

	/*
	 * (non-Javadoc)
	 * @see com.core.drools.RuleEngine#execute(com.core.drools.EntityRule)
	 */
	@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();
	}
	
	/**
	 * Read the rule files.
	 * @return
	 * @throws Exception
	 */
	private PackageBuilder getPackageBuilderFile()throws Exception {
		/** Get the rule files. */
		List<String> drlFilePath = getRuleFile();
		/** Sets the file to 'readers'. */
		List<Reader> readers = loadRuleFile(drlFilePath);
		/** To create the 'backageBuilder'. */
		PackageBuilder backageBuilder = new PackageBuilder();
		for (Reader r : readers) {
			backageBuilder.addPackageFromDrl(r);
		}
		/** Check if the script has a problem. */
		if(backageBuilder.hasErrors()) {
			throw new Exception(backageBuilder.getErrors().toString());
		}
		return backageBuilder;
	}
	
	/**
	 * Load the script files.
	 * @param drlFilePath 
	 * @return
	 * @throws FileNotFoundException
	 */
	private List<Reader> loadRuleFile(List<String> drlFilePath)
		throws FileNotFoundException {
		if (null == drlFilePath || 0 == drlFilePath.size()) {
			return null;
		}
		List<Reader> readers = new ArrayList<Reader>();
		for (String ruleFilePath : drlFilePath) {
			readers.add(new FileReader(new File(ruleFilePath)));
		}
		return readers;
	}

	/**
	 * Get the rule files.
	 * @return
	 */
	private List<String> getRuleFile(){
		List<String> drlFilePath = new ArrayList<String>();
		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;

/**
 * To create a singleton factory.
 * @author Candy
 *
 */
public class SingleRuleFactory {
	
	private static RuleBase ruleBase;
	
	/**
	 * Get the base factory.
	 * @return
	 */
	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;

/**
 * Test Drools
 * @author Candy
 *
 */
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

© 著作权归作者所有

共有 人打赏支持
Candy_Desire
粉丝 31
博文 71
码字总数 84592
作品 0
浦东
产品经理
私信 提问
加载中

评论(1)

达人不是我
达人不是我
Drools规则工作流引擎开发教程
网盘地址:http://pan.baidu.com/s/1boavEAN 密码:q4e0
备用地址(腾讯微云):http://url.cn/5NZUh5b 密码:rhO85Y
Drools7.x环境搭建与简单示例

Drools是个规则引擎的开源实现。官方文档比较长。这里提供一个方法,搭建最基本的Drools运行环境,并提供一个简单示例。 环境准备: JDK 至少需要JDK 1.5以上,JDK去这里下载:http://www.or...

supergao222
2018/01/10
0
0
Drools 6.2.0.Beta1 发布

Drools 6.2.0.Beta1 发布,此版本引入了一个新的 Drools Execution Server。更多内容请看这里。 Drools 是用 Java 语言编写的开放源码规则引擎,使用 Rete 算法对所编写的规则求值。Drools ...

叶秀兰
2014/08/17
2K
1
Drools 6.4.0.Final 发布,Java 业务规则引擎

Drools 6.4.0.Final 发布了,Drools 是用 Java 语言编写的开放源码规则引擎,使用 Rete 算法对所编写的规则求值。Drools 允许使用声明方式表达业务逻辑。可以使用非 XML 的本地语言编写规则,...

oschina
2016/04/19
3.1K
4
Drools 6.2.0.Final 发布,Java 业务规则引擎

Drools 6.2.0.Final 发布,此版本主要关注可用性和易用性方面的改进:Workbench UI;支持社会活动和插件管理;规则方面全新的 Execution Server。 相关链接: News & Noteworthy Downloads ...

叶秀兰
2015/03/07
5.4K
1
Drools 6.3.0.Final 发布,Java 业务规则引擎

Drools 6.3.0.Final 发布,此版本主要是平台的扩展和改进。 相关内容: Downloads Documentation Release Notes Drools 6.3 是跟 jBPM 一起发布的,主要改进: 实时验证和 Decision 表认证 ...

叶秀兰
2015/09/29
3.2K
4

没有更多内容

加载失败,请刷新页面

加载更多

【PG内核】事务ID冷冻简述

数据库代码中事务ID的类型TransactionId定义为:typedef uint32 TransactionId。因此事务ID最大值为2^32-1=4294967295。 事务ID是需要循环使用的,为了做到这一点,数据库在做vacuum时将很老...

movead
26分钟前
13
0
深入学习SpringMVC以及学习总结

一、优点: 1.SpringMVC简化web程序开发; 2.SpringMVC效率很好(单例模式); 3.SpringMVC提供了大量扩展点,方便程序员自定义功能; 如果想学习Java工程化、高性能及分布式、深入浅出。微服...

编程SHA
26分钟前
1
0
关于开源分布式事务中间件Fescar,我们总结了开发者关心的13个问题

开源分布式事务中间件 Fescar 自1月10日上线v0.1版本以来,受到了开发者们的极大关注(watch249,star3005,fork649,社区讨论的issue58,数据统计于1月17日14:00),可见,天下苦分布式事务...

阿里云官方博客
26分钟前
1
0
斯皮格尔:我们敢于采纳非常疯狂的创意

“阅后即焚”照片分享应用 Snapchat 母公司 Snap 的 CEO 埃文-斯皮格尔(Evan Spiegel)近日接受了英国《金融时报》记者的采访,谈到了该公司的未来发展,与社交网络 Facebook 的竞争,限制自己...

linuxCool
27分钟前
1
0
javaweb文件上传以及文件上传成功后但是目录中没有显示

经过看别人写的代码然后自己实际操作一遍,基本都是搬运也是为了练习。1:创建fileUpLoad.jsp<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UT......

小橙子的曼曼
29分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部