Ejemplo de motor de reglas Drools

Las irregularidades no forman un círculo, y lo mismo ocurre en el campo del software. Por ejemplo, la "regla de puntos de membresía" más común. El registro de miembros tiene un punto original. Esto es fácil de manejar. Inicialice un valor original al crear un nuevo objeto. Entonces el valor original también es Como registro normal, registro de vacaciones, etc., el valor original será diferente. Esta es una regla; también existe la fecha de vigencia del registro, por ejemplo, con vigencia inmediata, con vigencia dentro de los tres días, Esto también es una regla; consumo de miembros También habrá múltiples reglas, como consumo ordinario, consumo de vacaciones y consumo de cumpleaños; los tiempos de consumo de membresía y los descuentos también producirán múltiples reglas, como el consumo de vacaciones y los descuentos de consumo ordinario, y los descuentos por consumo diario son diferentes ..... ..

De esta manera, las reglas pueden describirse como diversas y vertiginosas, y los principiantes pueden juzgar infinitamente con unos pocos if / else, entonces esto se puede hacer, sin mencionar la dificultad del mantenimiento futuro (incluso a veces no lo hace. ), su cuerpo ejecutivo solo es suficiente para hincharse; las personas con un poco de experiencia pueden elegir algunos patrones de diseño, como patrón de fábrica, patrón de adaptador, etc., y luego hay un problema, solo una regla Produce innumerables objetos de implementación. Si hay algunas reglas más, entonces su sistema es lo suficientemente grande como para asfixiar a la gente.

Entonces nos preguntaremos si hay alguna forma de que modifiquemos unos archivos de configuración para solucionar estos problemas sin afectar la estructura de todo el sistema, es decir, para lograr el llamado acoplamiento suelto. ¡Así nació Drools!

Drools es un negocio de código abierto bajo JBOOS. Las cosas de código abierto son emocionantes, porque no solo es gratis, sino que también nos permite a los programadores dar rienda suelta a lo que hemos visto.

No hay tonterías, implementemos un pequeño ejemplo de puntos de membresía, el misterio aparecerá naturalmente:

Para construir un proyecto bajo eclipse, porque simplemente resolví los pasos de implementación para todos, así que solo construí un proyecto java simple:

Importe el paquete ar relacionado con j requerido por drools, vea la captura de pantalla:

 

Luego agregamos una clase java para declarar los parámetros de la integración primero:

package com.drools.demo.point;


/**
 * 积分计算对象
 * @author quzishen
 */
public class PointDomain {
	// 用户名
	private String userName;
	// 是否当日生日 
	private boolean birthDay;
	// 增加积分数目
	private long point;
	// 当月购物次数
	private int buyNums;
	// 当月退货次数
	private int backNums;
	// 当月购物总金额
	private double buyMoney;
	// 当月退货总金额
	private double backMondy;
	// 当月信用卡还款次数
	private int billThisMonth;
	public boolean isBirthDay() {
		return birthDay;
	}

	public void setBirthDay(boolean birthDay) {
		this.birthDay = birthDay;
	}

	public long getPoint() {
		return point;
	}

	public void setPoint(long point) {
		this.point = point;
	}

	public int getBuyNums() {
		return buyNums;
	}

	public void setBuyNums(int buyNums) {
		this.buyNums = buyNums;
	}

	public int getBackNums() {
		return backNums;
	}

	public void setBackNums(int backNums) {
		this.backNums = backNums;
	}

	public double getBuyMoney() {
		return buyMoney;
	}

	public void setBuyMoney(double buyMoney) {
		this.buyMoney = buyMoney;
	}

	public double getBackMondy() {
		return backMondy;
	}

	public void setBackMondy(double backMondy) {
		this.backMondy = backMondy;
	}

	public int getBillThisMonth() {
		return billThisMonth;
	}

	public void setBillThisMonth(int billThisMonth) {
		this.billThisMonth = billThisMonth;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserName() {
		return userName;
	}
	/**
	 * 记录积分发送流水,防止重复发放
	 * @param userName 用户名
	 * @param type 积分发放类型
	 */
	public void recordPointLog(String userName, String type){
		System.out.println("增加对"+userName+"的类型为"+type+"的积分操作记录.");
	}
}

Después de definir el objeto de regla, tenemos que definir sus reglas, crear un nuevo archivo de reglas en el directorio src, addpoint.drl

editar:

package com.drools.demo.point

import com.drools.demo.point.PointDomain;
 
rule birthdayPoint
	// 过生日,则加10分,并且将当月交易比数翻倍后再计算积分
	salience 100
	lock-on-active true
	when
		$pointDomain : PointDomain(birthDay == true)
	then
		$pointDomain.setPoint($pointDomain.getPoint()+10);
		$pointDomain.setBuyNums($pointDomain.getBuyNums()*2);
		$pointDomain.setBuyMoney($pointDomain.getBuyMoney()*2);
		$pointDomain.setBillThisMonth($pointDomain.getBillThisMonth()*2);
		
		$pointDomain.recordPointLog($pointDomain.getUserName(),"birthdayPoint");
end

rule billThisMonthPoint
	// 2011-01-08 - 2011-08-08每月信用卡还款3次以上,每满3笔赠送30分
	salience 99
	lock-on-active true
	date-effective "2011-01-08 23:59:59"
	date-expires "2011-08-08 23:59:59"
	when
		$pointDomain : PointDomain(billThisMonth >= 3)
	then
		$pointDomain.setPoint($pointDomain.getPoint()+$pointDomain.getBillThisMonth()/3*30);
		$pointDomain.recordPointLog($pointDomain.getUserName(),"billThisMonthPoint");
end

rule buyMoneyPoint
	// 当月购物总金额100以上,每100元赠送10分
	salience 98
	lock-on-active true
	when
		$pointDomain : PointDomain(buyMoney >= 100)
	then
		$pointDomain.setPoint($pointDomain.getPoint()+ (int)$pointDomain.getBuyMoney()/100 * 10);
		$pointDomain.recordPointLog($pointDomain.getUserName(),"buyMoneyPoint");
end

rule buyNumsPoint
	// 当月购物次数5次以上,每五次赠送50分
	salience 97
	lock-on-active true
	when
		$pointDomain : PointDomain(buyNums >= 5)
	then
		$pointDomain.setPoint($pointDomain.getPoint()+$pointDomain.getBuyNums()/5 * 50);
		$pointDomain.recordPointLog($pointDomain.getUserName(),"buyNumsPoint");
end

rule allFitPoint
	// 特别的,如果全部满足了要求,则额外奖励100分
	salience 96
	lock-on-active true
	when
		$pointDomain:PointDomain(buyNums >= 5 && billThisMonth >= 3 && buyMoney >= 100)
	then
		$pointDomain.setPoint($pointDomain.getPoint()+ 100);
		$pointDomain.recordPointLog($pointDomain.getUserName(),"allFitPoint");
end

 

Necesitamos definir una clase de fábrica de motores para generar las herramientas de motor que necesitamos

import org.drools.RuleBase;
import org.drools.RuleBaseFactory;

/**
 * RuleBaseFacatory 单实例RuleBase生成工具
 * @author quzishen
 */
public class RuleBaseFacatory {
	private static RuleBase ruleBase;
	
	public static RuleBase getRuleBase(){
		return null != ruleBase ? ruleBase : RuleBaseFactory.newRuleBase();
	}
}


 

A continuación, definimos una interfaz para las reglas de integración y completamos tres cosas: inicializar las reglas de integración, ejecutar las reglas y actualizar las reglas.

import com.drools.demo.point.PointDomain;

/**
 * 规则接口
 * @author quzishen
 */
public interface PointRuleEngine {
	
	/**
	 * 初始化规则引擎
	 */
	public void initEngine();
	
	/**
	 * 刷新规则引擎中的规则
	 */
	public void refreshEnginRule();
	
	/**
	 * 执行规则引擎
	 * @param pointDomain 积分Fact
	 */
	public void executeRuleEngine(final PointDomain pointDomain);
}


Clase de implementación:

import java.io.File;

/**
 * 规则接口实现类
 * @author quzishen
 */
public class PointRuleEngineImpl implements PointRuleEngine {
	private RuleBase ruleBase;

	/* (non-Javadoc)
	 * @see com.drools.demo.point.PointRuleEngine#initEngine()
	 */
	public void initEngine() {
		// 设置时间格式
		System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
		ruleBase = RuleBaseFacatory.getRuleBase();
		try {
			PackageBuilder backageBuilder = getPackageBuilderFromDrlFile();
			ruleBase.addPackage(backageBuilder.getPackage());
		} catch (DroolsParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/* (non-Javadoc)
	 * @see com.drools.demo.point.PointRuleEngine#refreshEnginRule()
	 */
	public void refreshEnginRule() {
		ruleBase = RuleBaseFacatory.getRuleBase();
		org.drools.rule.Package[] packages = ruleBase.getPackages();
		for(org.drools.rule.Package pg : packages) {
			ruleBase.removePackage(pg.getName());
		}
		
		initEngine();
	}

	/* (non-Javadoc)
	 * @see com.drools.demo.point.PointRuleEngine#executeRuleEngine(com.drools.demo.point.PointDomain)
	 */
	public void executeRuleEngine(final PointDomain pointDomain) {
		if(null == ruleBase.getPackages() || 0 == ruleBase.getPackages().length) {
			return;
		}
		
		StatefulSession statefulSession = ruleBase.newStatefulSession();
		statefulSession.insert(pointDomain);
		
		// fire
		statefulSession.fireAllRules(new org.drools.spi.AgendaFilter() {
			public boolean accept(Activation activation) {
				return !activation.getRule().getName().contains("_test");
			}
		});
		
		statefulSession.dispose();
	}

	/**
	 * 从Drl规则文件中读取规则
	 * @return
	 * @throws Exception
	 */
	private PackageBuilder getPackageBuilderFromDrlFile() throws Exception {
		// 获取测试脚本文件
		List<String> drlFilePath = getTestDrlFile();
		// 装载测试脚本文件
		List<Reader> readers = readRuleFromDrlFile(drlFilePath);

		PackageBuilder backageBuilder = new PackageBuilder();
		for (Reader r : readers) {
			backageBuilder.addPackageFromDrl(r);
		}
		
		// 检查脚本是否有问题
		if(backageBuilder.hasErrors()) {
			throw new Exception(backageBuilder.getErrors().toString());
		}
		
		return backageBuilder;
	}

	/**
	 * @param drlFilePath 脚本文件路径
	 * @return
	 * @throws FileNotFoundException
	 */
	private List<Reader> readRuleFromDrlFile(List<String> drlFilePath) throws FileNotFoundException {
		if (null == drlFilePath || 0 == drlFilePath.size()) {
			return null;
		}

		List<Reader> readers = new ArrayList<Reader>();

		for (String ruleFilePath : drlFilePath) {
			File file=new File(ruleFilePath);
			readers.add(new FileReader(file));
		}

		return readers;
	}

	/**
	 * 获取测试规则文件
	 * 
	 * @return
	 */
	private List<String> getTestDrlFile() {
		List<String> drlFilePath = new ArrayList<String>();
		URL url=this.getClass().getResource("/");
		drlFilePath
				.add(url.getPath().replaceAll("\\\\", "/")+"addpoint.drl");
		drlFilePath
				.add(url.getPath().replaceAll("\\\\", "/")+"subpoint.drl");

		return drlFilePath;
	}
}

Bien, probémoslo:

import java.io.BufferedReader;


public class Test {
	public static void main(String[] args) throws IOException {
		PointRuleEngine pointRuleEngine = new PointRuleEngineImpl();
		while(true){
			InputStream is = System.in;
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String input = br.readLine();
			
			if(null != input && "s".equals(input)){
				System.out.println("初始化规则引擎...");
				pointRuleEngine.initEngine();
				System.out.println("初始化规则引擎结束.");
			}else if("e".equals(input)){
				final PointDomain pointDomain = new PointDomain();
				pointDomain.setUserName("hello kity");
				pointDomain.setBackMondy(100d);
				pointDomain.setBuyMoney(500d);
				pointDomain.setBackNums(1);
				pointDomain.setBuyNums(5);
				pointDomain.setBillThisMonth(5);
				pointDomain.setBirthDay(true);
				pointDomain.setPoint(0l);
				
				pointRuleEngine.executeRuleEngine(pointDomain);
				
				System.out.println("执行完毕BillThisMonth:"+pointDomain.getBillThisMonth());
				System.out.println("执行完毕BuyMoney:"+pointDomain.getBuyMoney());
				System.out.println("执行完毕BuyNums:"+pointDomain.getBuyNums());
				System.out.println("执行完毕BackNums:"+pointDomain.getBackNums());
				System.out.println("执行完毕BackMondy:"+pointDomain.getBackMondy());
				System.out.println("执行完毕规则引擎决定发送积分:"+pointDomain.getPoint());
			} else if("r".equals(input)){
				System.out.println("刷新规则文件...");
				pointRuleEngine.refreshEnginRule();
				System.out.println("刷新规则文件结束.");
			}
		}
	}
}


Resultados de:

s
初始化规则引擎...
初始化规则引擎结束.

e
增加对hello kity的类型为birthdayPoint的积分操作记录.
增加对hello kity的类型为buyMoneyPoint的积分操作记录.
增加对hello kity的类型为buyNumsPoint的积分操作记录.
增加对hello kity的类型为allFitPoint的积分操作记录.
增加对hello kity的类型为subBackNumsPoint的积分操作记录.
增加对hello kity的类型为subBackMondyPoint的积分操作记录.
执行完毕BillThisMonth:10
执行完毕BuyMoney:1000.0
执行完毕BuyNums:10
执行完毕BackNums:1
执行完毕BackMondy:100.0
执行完毕规则引擎决定发送积分:490
r
刷新规则文件...
刷新规则文件结束.



 El enlace de descarga del proyecto completo: http://download.csdn.net/detail/huxiang19851114/4697914

Supongo que te gusta

Origin blog.csdn.net/huxiang19851114/article/details/8123524
Recomendado
Clasificación