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

发表于:2018-4-17 09:11  作者:未知   来源:阿里云

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签: 软件开发 java JAVA

  随着互联网应用的飞速发展,各种业务需求也应运而生,对于不断变更和革新的业务规则而言,项目的开发就很有必要把规则部分独立提取出来,此时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 = getPack
  ageBuilderFile();
  /** 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 getPackageBuild
  erFile()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



上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。

评 论

论坛新帖

顶部 底部


建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海瀛东律师事务所 张楠律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2018, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道