天天看点

drools7 DRL规则语言之二(package、import、function)一、package和import二、function

      本文将简介package、import组件,会较多的介绍function组件。

一、package和import

      这么大的标题,其实没什么可介绍的。本来也没想写这两部分,但是为了完整,还是凑了两句。

      package 实际就是一个符合java命名规范的域名,多个drl文件可重复使用,namespace跟drl文件的保存路径并没有关系,可任意定义,但是位置必须是声明在文件的顶部。在被其他drl文件引用时、规则单元分组时有很大的用处。

      import用于引用java项目或其他依赖包中的类库、引用其他drl文件中的function等资源。

二、function

    function虽然作为本文的介绍重心,但是用法却是极其的简单易懂,与java中的方法一样,可以有入参和返回值,根据方法签名调用function。when和then中都可以调用function,其作用就是提高代码重复利用率。但我在实际使用过程中却发现,往往在较复杂的条件逻辑判断时function特别有用。

   首先,还是简单的示例:

package rules;
import com.helloworld.bean.Student
function String  printFun(String name){
    return "hello,"+name;
}

rule "rule"
    when
        Student($n:name)
    then
        System.out.println(printFun($n));
end
           

     简单的示例仅适合入门了解,以前的文章写过一个用function校验日期时间段的例子,这里简化一下拿来做个说明吧。

示例:某商场为了吸引客户消费,决定在4月1日到4月30日给予到店客户9折优惠。
           

定义实体类如下:

public class Customer {
    private Integer id;
    private String name;
    private double discount;//折扣率
    private boolean freeParking;//是否免费停车
}
           

数据如下:

//规则文件,生成知识库并创建会话
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession();
//创建并插入源数据        
Customer customer = new Customer();
customer.setId(1);
customer.setDiscount(0.0);
customer.setFreeParking(false);
customer.setName("杨杨");
kieSession.insert(customer);
//规则校验        
kieSession.fireAllRules();
//释放资源,关闭会话
kieSession.dispose();
           

规则定义如下:

package rules;
import com.helloworld.bean.Customer
import java.util.Date
import java.text.SimpleDateFormat
//校验时间
function boolean dateFunc(){
      Date date = new Date();
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      Date date1 = sdf.parse("2020-04-01");
      Date date2 = sdf.parse("2020-04-30");
      if(date.after(date1) && date.before(date2)){
       return true;
      }
      return false;
}

rule "rule"
//date-effective "2020-04-01"
//date-expires "2020-04-30"
    when
        eval(dateFunc())
        $c:Customer()
    then
       $c.setDiscount(0.90);
       System.out.println("尊敬的"+$c.getName()+",您将享受"+$c.getDiscount()*10+"折优惠!");
end
           

执行结果如下:

尊敬的杨杨,您将享受9.0折优惠!
           

当然上述示例使用 date-effective 和 date-expires 两个属性更方便,但是这两个属性只能控制日期区间,如果更细化判断就有点力不从心了。下面将对上述需求做出修改如下:

示例:
优惠一:4月1日至4月30日给予客户9折优惠;
优惠二:同时为了避免早晚高峰期,过多的客户到店消费造成拥堵,商场提出提出另一项优惠,每天14:00至16:00免费停车
           

除了校验日期,还需要对时间段做出判断。规则如下:

package rules;
import com.helloworld.bean.Customer
import java.util.Date
import java.text.SimpleDateFormat
import java.util.Calendar
function boolean dateFunc(){
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       Date date = sdf.parse(sdf.format(new Date()));
      Date date1 = sdf.parse("2020-04-01");
      Date date2 = sdf.parse("2020-04-30");
      if(date.after(date1) && date.before(date2)){
       return true;
      }
      return false;
}
function boolean timeFunc(){
  SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
  // Date date = sdf.parse(sdf.format(new Date()));
  //写案例的时候已经18点了,这里就伪造个时间点吧
  Date date = sdf.parse("15:30:10");
  Date date1 = sdf.parse("14:00");
  Date date2 = sdf.parse("16:00");
  if(date.after(date1) && date.before(date2)){
   return true;
  }
  return false;
}
rule "rule"
    when
        eval(dateFunc())
        $c:Customer()
        do[discount]
        eval(timeFunc())
    then
         $c.setFreeParking(true);
         System.out.println("尊敬的"+$c.getName()+",您本次停车免费");
    then[discount]
       $c.setDiscount(0.90);
       System.out.println("尊敬的"+$c.getName()+",您将享受"+$c.getDiscount()*10+"折优惠!");

end
           

运行结果如下:

尊敬的杨杨,您将享受9.0折优惠!
尊敬的杨杨,您本次停车免费
           

        还可以通过 import function 引入静态java方法,与global相似,但是它只能引用静态方法,下面用import function写出上述示例:

静态方法如下:

package com.helloworld.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateService {
    public static  boolean dateFunc(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(sdf.format(new Date()));
            Date date1 = sdf.parse("2020-04-01");
            Date date2 = sdf.parse("2020-04-30");
            if(date.after(date1) && date.before(date2)){
                return true;
            }
            return false;
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }

    }
}
           

规则文件如下:

package rules;
import com.helloworld.bean.Customer
import java.util.Date
import java.text.SimpleDateFormat
//引入java静态类
import function com.helloworld.service.DateService.dateFunc

/*function boolean dateFunc(){
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       Date date = sdf.parse(sdf.format(new Date()));
      Date date1 = sdf.parse("2020-04-01");
      Date date2 = sdf.parse("2020-04-30");
      if(date.after(date1) && date.before(date2)){
       return true;
      }
      return false;
}*/
function boolean timeFunc(){
  SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
  // Date date = sdf.parse(sdf.format(new Date()));
  Date date = sdf.parse("15:30:10");
  Date date1 = sdf.parse("14:00");
  Date date2 = sdf.parse("16:00");
  if(date.after(date1) && date.before(date2)){
   return true;
  }
  return false;
}
rule "rule"
    when
        eval(dateFunc())
        $c:Customer()
        do[discount]
        eval(timeFunc())
    then
         $c.setFreeParking(true);
         System.out.println("尊敬的"+$c.getName()+",您本次停车免费");
    then[discount]
       $c.setDiscount(0.90);
       System.out.println("尊敬的"+$c.getName()+",您将享受"+$c.getDiscount()*10+"折优惠!");

end
           

运行结果如下:

尊敬的杨杨,您将享受9.0折优惠!
尊敬的杨杨,您本次停车免费
           

function的作用还是挺大的,还可以用它来做集合遍历、数据预处理等等,更多的应用场景等着各位去发现。