简单drools规则java代码自动生成

来源:互联网 发布:查看mysql启动状态 编辑:程序博客网 时间:2024/06/06 10:53

简单drools规则自动生成



  规则自动生成,drools也提供了支持,比如:
1.决策表(decision table)https://docs.jboss.org/drools/release/6.5.0.Final/drools-docs/html_single/index.html#d0e5713,

2.规则模板(Rule Templates)https://docs.jboss.org/drools/release/6.5.0.Final/drools-docs/html_single/index.html#d0e6464

3. 流式API http://docs.jboss.org/drools/release/5.2.0.Final/droolsjbpm-introduction-docs/html/ch02.html#d0e124

  不过由于现实环境中,我们会根据Excel 文件提供规则描述,解析动态生成规则,如果产品给的是决策表,那就很容易了,不过产品一般会根据自己的喜好,制定自己的"决策表".

  比如:(一行放不下,截取了两种图)


      博文http://blog.csdn.net/doctor_who2004/article/details/72600232介绍了如何读取Excel文件转换为java类,此不复述。
    文件中的内容对应的java类:

package com.beaver.drools.exampl.travel.rule;import org.javafunk.excelparser.annotations.ExcelField;import org.javafunk.excelparser.annotations.ExcelObject;import org.javafunk.excelparser.annotations.ParseType;/** * Created by beaver on 2017/5/20. */@ExcelObject(parseType = ParseType.ROW, start = 2, end = 61)public class TravelRule {        //公司名称    @ExcelField(position = 1)    private String companyName;        //费用类型    @ExcelField(position = 2)    private String expenseType;        //规则应用场景    @ExcelField(position = 3)    private String applyPoint;        //规则结果    @ExcelField(position = 4)    private String ruleAction;        //规则内容    @ExcelField(position = 7)    private String rule;        //提示信息    @ExcelField(position = 9)    private String alertMessage;        //规则ID    @ExcelField(position = 11)    private String ruleId;        //解析出的drools规则内容    private String droolsRule;        public String getCompanyName() {        return companyName;    }        public void setCompanyName(String companyName) {        this.companyName = companyName;    }        public String getExpenseType() {        return expenseType;    }        public void setExpenseType(String expenseType) {        this.expenseType = expenseType;    }        public String getRule() {        return rule;    }        public void setRule(String rule) {        this.rule = rule;    }        public String getApplyPoint() {        return applyPoint;    }        public void setApplyPoint(String applyPoint) {        this.applyPoint = applyPoint;    }        public String getRuleAction() {        return ruleAction;    }        public void setRuleAction(String ruleAction) {        this.ruleAction = ruleAction;    }        public String getAlertMessage() {        return alertMessage;    }        public void setAlertMessage(String alertMessage) {        this.alertMessage = alertMessage;    }        public String getRuleId() {        return ruleId;    }        public void setRuleId(String ruleId) {        this.ruleId = ruleId;    }        public String getDroolsRule() {        return droolsRule;    }        public void setDroolsRule(String droolsRule) {        this.droolsRule = droolsRule;    }        @Override    public String toString() {        return "TravelRule{" +                "companyName='" + companyName + '\'' +                ", expenseType='" + expenseType + '\'' +                ", applyPoint='" + applyPoint + '\'' +                ", ruleAction='" + ruleAction + '\'' +                ", rule='" + rule + '\'' +                ", alertMessage='" + alertMessage + '\'' +                ", ruleId='" + ruleId + '\'' +                ", droolsRule='" + droolsRule + '\'' +                '}';    }}

   规则内when条件的匹配对象一般我们使用java中自定义的类最好,此类为:


package com.beaver.drools.exampl.travel.rule;import com.beaver.drools.common.model.RuleResult;import lombok.Data;import java.util.HashMap;import java.util.Map;/** * Created by beaver on 2017/5/20. */@Datapublic class MatchInvoiceTravelRuleRequestDto {    //规则ID    private String ruleOID;        //出差申请ID    private String invoiceOID;        //出差信息-人员级别、出差地点、出差费用等等    private Map<String, String> data = new HashMap<>();        //规则执行结果    private RuleResult result = RuleResult.OK;        //备注-规则明细    private String remarkMessage;    }

   本博文只是实现简单drools规则的自动生成,一个简单的规则的定义如下:

package com.beaver.drools.exampl.travel.rule;import com.beaver.drools.common.model.RuleResult;import com.google.common.base.Splitter;import org.apache.commons.lang3.StringUtils;import org.apache.commons.lang3.tuple.Pair;import java.util.*;import java.util.Map.Entry;import java.util.regex.Matcher;import java.util.regex.Pattern;import java.util.stream.Collectors;/** * Created by beaver on 2017/5/20.<br> * 简单规则组成,并不不包含drools复杂的语法规则 */public class TravelRuleGenerate {    //规则包名    private String packageName;    //规则需要外部类的包    private List<String> importPackages = new ArrayList<>();    //规则名字    private String ruleName;        //规则匹配的类型,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem    private String objectType;        //规则匹配类型的变量名,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem中$o    private String objectVar;        //规则信息    private TravelRule travelRule;        //规则执行动作结果赋值属性名,如 $invoice.setResult(RuleResult.REJECT); 中的resultr;    private String resultPropertyName;    //规则执行动作结果的提示信息赋值属性名,如   $invoice.setRemarkMessage("您的房费高于公司标准 ");中的remarkMessage.    private String alertMessagePropertyName;        //规则匹配属性别名,如data["EXPENSE_LEVEL"] not in ("总裁"),    // 中的EXPENSE_LEVEL在travelRule中droolsRule中的名不一样,类似mybatis映射一下    //不过key为正则表达式    private Map<String, String> rulePropertyNameAlias = new HashMap<>();        public String getPackageName() {        return packageName;    }        public void setPackageName(String packageName) {        this.packageName = packageName;    }        public List<String> getImportPackages() {        return importPackages;    }        public void setImportPackages(List<String> importPackages) {        this.importPackages = importPackages;    }        public String getRuleName() {        return ruleName;    }        public void setRuleName(String ruleName) {        this.ruleName = ruleName;    }        public TravelRule getTravelRule() {        return travelRule;    }        public void setTravelRule(TravelRule travelRule) {        this.travelRule = travelRule;    }        public String getObjectType() {        return objectType;    }        public void setObjectType(String objectType) {        this.objectType = objectType;    }        public String getObjectVar() {        return objectVar;    }        public void setObjectVar(String objectVar) {        this.objectVar = objectVar;    }        public String getResultPropertyName() {        return resultPropertyName;    }        public void setResultPropertyName(String resultPropertyName) {        this.resultPropertyName = resultPropertyName;    }        public String getAlertMessagePropertyName() {        return alertMessagePropertyName;    }        public void setAlertMessagePropertyName(String alertMessagePropertyName) {        this.alertMessagePropertyName = alertMessagePropertyName;    }        public Map<String, String> getRulePropertyNameAlias() {        return rulePropertyNameAlias;    }        public void setRulePropertyNameAlias(Map<String, String> rulePropertyNameAlias) {        this.rulePropertyNameAlias = rulePropertyNameAlias;    }    }


其中
//规则信息private TravelRule travelRule;
是我们解析Excel文件得到的原生规则,我们需要对其处理,生成drools规则描述。

下面的定义主要是为业务和代码需求定制,Excel文件中规则属性名多个对应一个意思,后者和我们java代码定义的不一样,所以类似mybatis,做个映射。
//规则匹配属性别名,如data["EXPENSE_LEVEL"] not in ("总裁"),// 中的EXPENSE_LEVEL在travelRule中droolsRule中的名不一样,类似mybatis映射一下//不过key为正则表达式private Map<String, String> rulePropertyNameAlias = new HashMap<>();

下面代码是对
private TravelRule travelRule;
及本类提供的规则信息产生drools规则,实现是比较笨重的方法,因为规则比较简单,复杂的规则如何实现呢?


package com.beaver.drools.exampl.travel.rule;import com.beaver.drools.common.model.RuleResult;import com.google.common.base.Splitter;import org.apache.commons.lang3.StringUtils;import org.apache.commons.lang3.tuple.Pair;import java.util.*;import java.util.Map.Entry;import java.util.regex.Matcher;import java.util.regex.Pattern;import java.util.stream.Collectors;/** * Created by beaver on 2017/5/20.<br> * 简单规则组成,并不不包含drools复杂的语法规则 */public class TravelRuleGenerate {    //规则包名    private String packageName;    //规则需要外部类的包    private List<String> importPackages = new ArrayList<>();    //规则名字    private String ruleName;        //规则匹配的类型,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem    private String objectType;        //规则匹配类型的变量名,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem中$o    private String objectVar;        //规则信息    private TravelRule travelRule;        //规则执行动作结果赋值属性名,如 $invoice.setResult(RuleResult.REJECT); 中的resultr;    private String resultPropertyName;    //规则执行动作结果的提示信息赋值属性名,如   $invoice.setRemarkMessage("您的房费高于公司标准 ");中的remarkMessage.    private String alertMessagePropertyName;        //规则匹配属性别名,如data["EXPENSE_LEVEL"] not in ("总裁"),    // 中的EXPENSE_LEVEL在travelRule中droolsRule中的名不一样,类似mybatis映射一下    //不过key为正则表达式    private Map<String, String> rulePropertyNameAlias = new HashMap<>();        public String getPackageName() {        return packageName;    }        public void setPackageName(String packageName) {        this.packageName = packageName;    }        public List<String> getImportPackages() {        return importPackages;    }        public void setImportPackages(List<String> importPackages) {        this.importPackages = importPackages;    }        public String getRuleName() {        return ruleName;    }        public void setRuleName(String ruleName) {        this.ruleName = ruleName;    }        public TravelRule getTravelRule() {        return travelRule;    }        public void setTravelRule(TravelRule travelRule) {        this.travelRule = travelRule;    }        public String getObjectType() {        return objectType;    }        public void setObjectType(String objectType) {        this.objectType = objectType;    }        public String getObjectVar() {        return objectVar;    }        public void setObjectVar(String objectVar) {        this.objectVar = objectVar;    }        public String getResultPropertyName() {        return resultPropertyName;    }        public void setResultPropertyName(String resultPropertyName) {        this.resultPropertyName = resultPropertyName;    }        public String getAlertMessagePropertyName() {        return alertMessagePropertyName;    }        public void setAlertMessagePropertyName(String alertMessagePropertyName) {        this.alertMessagePropertyName = alertMessagePropertyName;    }        public Map<String, String> getRulePropertyNameAlias() {        return rulePropertyNameAlias;    }        public void setRulePropertyNameAlias(Map<String, String> rulePropertyNameAlias) {        this.rulePropertyNameAlias = rulePropertyNameAlias;    }        //规则生成    public String Generate() {        StringBuilder sb = new StringBuilder();                //规则头部        sb.append("package ").append(packageName).append("\n").append("\n");                importPackages.stream().forEach(t -> sb.append("import ").append(t).append("\n"));                sb.append("\n\n");                //规则名称        sb.append("rule  \"").append(generateRuleName()).append("\n\n");                //规则条件        sb.append("when").append("\n");        sb.append("  ").append(objectVar).append(" : ").append(objectType).append("(").append("\n");                //规则条件内容        List<String> rules = generateWhenContent();        rules.stream().forEach(t -> {            sb.append("  ").append(t).append(",\n");        });                int lastIndexOf = sb.lastIndexOf(",");        if (lastIndexOf > 0) {            sb.deleteCharAt(lastIndexOf);        }                sb.append(" ) \n");                        //规则执行动作        sb.append("then \n");                //规则执行结果        sb.append("  ").append(objectVar).append(".set").append(StringUtils.capitalize(resultPropertyName)).append("(");        RuleResult ruleResult = RuleResult.valueOf(travelRule.getRuleAction());        sb.append(RuleResult.class.getSimpleName()).append(".").append(ruleResult.name()).append("); \n");                //规则执行提示信息        sb.append("  ").append(objectVar).append(".set").append(StringUtils.capitalize(alertMessagePropertyName)).append("(\"");        sb.append(travelRule.getAlertMessage()).append(" \");");                sb.append("\n").append("end");        return sb.toString();    }        //{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*300    private List<String> generateWhenContent() {        String rule = travelRule.getRule().trim();        if (rule.contains("OR") || rule.contains("or")) {            throw new UnsupportedOperationException("请知悉drools 的基本使用:复杂的规则拆成简单的规则执行,or的规则请拆分");        }                if (rule.contains("and")) {            throw new UnsupportedOperationException("AND条件单词大写");        }                        List<String> ruelList = Splitter.on(Pattern.compile("AND")).trimResults().splitToList(rule);                List<String> rules = ruelList.stream().map(this::generateARule).collect(Collectors.toList());        return rules;    }        //去除AND条件的一条简单规则    private String generateARule(final String rule) {        if (StringUtils.deleteWhitespace(rule).contains("NOTIN")) {            Pair<String, String> pair = getRulePropertyNameAliasAndValuesForIn(rule, "NOT");            return pair.getKey() + " not in " + pair.getValue();        }                if (rule.contains("IN")) {            Pair<String, String> pair = getRulePropertyNameAliasAndValuesForIn(rule, "IN");            return pair.getKey() + " in " + pair.getValue();        }                if (rule.contains(">")) {            return getRulePropertyNameAliasAndValuesForCompare(rule, ">");        }                throw new UnsupportedOperationException();    }        //{EXP_LEVEL}IN[一般员工] , {ER_LOCATION}NOT IN[北京/上海/深圳]  to    //data["EXPENSE_LEVEL"] in ("一般员工"),data["city"] not in ("上海","北京","深圳","广州"),    private Pair<String, String> getRulePropertyNameAliasAndValuesForIn(final String rule, final String separators) {        String name = StringUtils.splitByWholeSeparator(rule, separators)[0];        name = getRulePropertyNameAlias(name).getValue();                name = "data[\"" + name + "\"]";                String value = StringUtils.substring(rule                , StringUtils.lastIndexOf(rule, "[") + 1                , StringUtils.lastIndexOf(rule, "]"));                List<String> values = Splitter.on("/").trimResults().splitToList(value);        value = values.stream().map(t -> "\"" + t + "\"").collect(Collectors.joining(","));        value = "(" + value + ")";        return Pair.of(name, value);    }        //{ER_EXP_FEE}>{ER_DAYS}*300     to    // BigDecimal.valueOf(Double.valueOf(data.["INVOICE_AMOUNT"])) > 300 * Double.valueOf(data["days"])    private String getRulePropertyNameAliasAndValuesForCompare(final String rule, final String separator) {        if (!Arrays.asList(">", "<", "=").contains(separator.trim())) {            throw new UnsupportedOperationException();        }                List<String> list = Splitter.on(separator.trim()).trimResults().splitToList(rule);        String express1 = list.get(0);        String express2 = list.get(1);        String template1 = "BigDecimal.valueOf(Double.valueOf(data[\"%s\"]))";        String tempalte2 = "Double.valueOf(data[\"%s\"])";                Pair<String, String> rulePropertyNameAlias1 = getRulePropertyNameAlias(express1);        express1 = String.format(template1, rulePropertyNameAlias1.getValue());                Pair<String, String> rulePropertyNameAlias2 = getRulePropertyNameAlias(express2);                express2 = String.format(tempalte2, rulePropertyNameAlias2.getValue());                String replace = rule.replace(rulePropertyNameAlias1.getKey(), express1);        replace = replace.replace(rulePropertyNameAlias2.getKey(), express2);        return replace;    }        private Pair<String, String> getRulePropertyNameAlias(final String content) {        for (Entry<String, String> entry : rulePropertyNameAlias.entrySet()) {            Pattern compile = Pattern.compile(entry.getKey());            Matcher matcher = compile.matcher(content);            if (matcher.find()) {                String name = content.substring(matcher.regionStart(), matcher.regionEnd());                String aliasName = entry.getValue();                return Pair.of(name, aliasName);            }        }                throw new UnsupportedOperationException(content);    }        private String generateRuleName() {        StringBuilder sb = new StringBuilder();        sb.append(travelRule.getCompanyName())          .append("-")          .append(travelRule.getExpenseType())          .append("-")          .append(ruleName).append("\"");                return sb.toString();    }    }

其中
 //规则生成
    public String Generate() {。。。}
方法主要是drools规则组装的实现。

我们测试一下:

package com.beaver.drools.exampl.travel.rule;import com.beaver.drools.util.KieSessionUtil;import com.google.gson.Gson;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.javafunk.excelparser.SheetParser;import org.kie.api.io.ResourceType;import java.io.IOException;import java.io.InputStream;import java.util.*;import java.util.stream.Collectors;/** * Created by beaver on 2017/5/20. */public class TravleRuelTest {        static String packageName = "com.beaver.drools.exampl.travel.rule";    static List<String> importPackages = Arrays.asList(            "java.math.*"            , "com.beaver.drools.common.model.*");            static String sheetName = "工作表1";    static String fileName = "腾讯差标规则1.xlsx";        static String objectType = "MatchInvoiceTravelRuleRequestDto";    static String objectVar = "$invoice";        static String resultPropertyName = "result";    static String alertMessagePropertyName = "remarkMessage";        //规则内容属性别名,如{EXP_LEVEL}IN[一般员工],EXP_LEVEL 可以起别名    static Map<String, String> rulePropertyNameAlias = new HashMap<>();        static {        rulePropertyNameAlias.put("\\{.*LEVEL.*\\}", "EXPENSE_LEVEL");        rulePropertyNameAlias.put("\\{.*LOCATION.*\\}", "city");        rulePropertyNameAlias.put("\\{.*FEE.*\\}", "INVOICE_AMOUNT");        rulePropertyNameAlias.put("\\{.*DAYS.*\\}", "days");    }        public static void main(String[] args) throws IOException {        //Get the sheet using POI API.        SheetParser parser = new SheetParser();        InputStream inputStream = TravleRuelTest.class.getClassLoader().getResourceAsStream(fileName);        Sheet sheet = new XSSFWorkbook(inputStream).getSheet(sheetName);        //Invoke the Sheet parser.        List<TravelRule> entityList = parser.createEntity(sheet, TravelRule.class, t -> t.printStackTrace());                //        entityList = entityList.stream()                               .filter(t -> t.getCompanyName() != null && !t.getCompanyName().isEmpty())                               .collect(Collectors.toList());                        System.out.println(new Gson().toJson(entityList));                Set<String> set = entityList.stream().map(TravelRule::getRuleId).collect(Collectors.toSet());        if (set.size() != entityList.size()) {            throw new IllegalArgumentException("id 有重复");        }                        entityList.stream()                  .map(TravleRuelTest::travelRuleGenerate)                  .forEach(t -> {                      System.out.println(t);                  });    }            public static TravelRule travelRuleGenerate(TravelRule travelRule) {        TravelRuleGenerate travelRuleGenerate = new TravelRuleGenerate();        travelRuleGenerate.setPackageName(packageName);        travelRuleGenerate.setImportPackages(importPackages);        travelRuleGenerate.setRuleName(travelRule.getRule());        travelRuleGenerate.setObjectType(objectType);        travelRuleGenerate.setObjectVar(objectVar);        travelRuleGenerate.setTravelRule(travelRule);        travelRuleGenerate.setResultPropertyName(resultPropertyName);        travelRuleGenerate.setAlertMessagePropertyName(alertMessagePropertyName);        travelRuleGenerate.setRulePropertyNameAlias(rulePropertyNameAlias);        String generate = travelRuleGenerate.Generate();                KieSessionUtil kieSessionUtil = new KieSessionUtil();        kieSessionUtil.addContent(generate, ResourceType.DRL);        kieSessionUtil.verifyRules();        travelRule.setDroolsRule(generate);        return travelRule;    }    }


输出:

..................................[  {    "companyName": "微民",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[1] AND {ER_EXP_FEE}\u003e{ER_DAYS} *600",    "alertMessage": "您的房费高于公司标准",    "ruleId": "8a24ef78-d1c4-4c7c-924f-f199fa3c5eb1"  },  {    "companyName": "微民",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[2] AND {ER_EXP_FEE}\u003e{ER_DAYS}*700",    "alertMessage": "您的房费高于公司标准",    "ruleId": "f9b17610-7917-4f71-b369-602224fdd20d"  },  {    "companyName": "微民",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[3] AND {ER_EXP_FEE}\u003e{ER_DAYS}*800",    "alertMessage": "您的房费高于公司标准",    "ruleId": "128e621a-832a-4876-81c8-a5a9624b6ca7"  },  {    "companyName": "微民",    "expenseType": "差旅补贴",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{ER_LOCATION_COUNTRY}IN[中国] AND {ER_EXP_FEE}\u003e{ER_DAYS}*140",    "alertMessage": "您的补贴高于公司标准",    "ruleId": "06d1afc9-4a0e-4ad6-b0b1-01af068997fe"  },  {    "companyName": "微民",    "expenseType": "差旅补贴",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{ER_LOCATION_COUNTRY}NOT IN[中国] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",    "alertMessage": "您的补贴高于公司标准",    "ruleId": "922d99ff-c5bc-4f26-a365-d8b6e8a9a999"  },  {    "companyName": "腾南",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[一般员工] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",    "alertMessage": "您的房费高于公司标准",    "ruleId": "7c170ce0-080e-499a-9046-0dc7d226b86c"  },  {    "companyName": "腾南",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}\u003e{ER_DAYS}*300",    "alertMessage": "您的房费高于公司标准",    "ruleId": "6135e677-867b-41ed-8d00-7512b5ec5c2a"  },  {    "companyName": "腾南",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[总监] AND {ER_EXP_FEE}\u003e{ER_DAYS}*550",    "alertMessage": "您的房费高于公司标准",    "ruleId": "636ebfda-6d78-4ec7-a441-234ff931fa57"  },  {    "companyName": "腾南",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[总监] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",    "alertMessage": "您的房费高于公司标准",    "ruleId": "b236a113-e547-4f65-9ddc-3b9549efa6ce"  },  {    "companyName": "腾南",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}\u003e{ER_DAYS}*700",    "alertMessage": "您的房费高于公司标准",    "ruleId": "8bb7e480-bf94-4c24-a46e-963ae60bee7e"  },  {    "companyName": "腾南",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}\u003e{ER_DAYS}*500",    "alertMessage": "您的房费高于公司标准",    "ruleId": "f74d0d7c-d31d-49d9-84ff-c0889bf37771"  },  {    "companyName": "腾南",    "expenseType": "差旅补贴",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{ER_EXP_FEE}\u003e{ER_DAYS}*80",    "alertMessage": "您的补贴高于公司标准",    "ruleId": "154866b0-fdc5-433f-9c3f-640e9a812564"  },  {    "companyName": "腾新",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}\u003e{ER_DAYS}*600",    "alertMessage": "您的房费高于公司标准",    "ruleId": "e4ece4c7-f9ca-46fc-bb7b-2a4443513daf"  },  {    "companyName": "腾新",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}NOT IN[总裁] AND {ER_EXP_FEE}\u003e{ER_DAYS}*500",    "alertMessage": "您的房费高于公司标准",    "ruleId": "51768055-8a13-4d44-9c61-e261bcb74149"  },  {    "companyName": "腾新",    "expenseType": "住宿费",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",    "alertMessage": "您的房费高于公司标准",    "ruleId": "0d3f86b6-f937-4544-916d-8fac5061c479"  },  {    "companyName": "腾新",    "expenseType": "差旅补贴",    "applyPoint": "ER_SUBMIT",    "ruleAction": "REJECT",    "rule": "{ER_EXP_FEE}\u003e{ER_DAYS}*100",    "alertMessage": "您的补贴高于公司标准",    "ruleId": "a9c0f423-7880-4f86-a761-ba2f2ec83c66"  }].....................TravelRule{companyName='微民', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[1] AND {ER_EXP_FEE}>{ER_DAYS} *600', alertMessage='您的房费高于公司标准', ruleId='8a24ef78-d1c4-4c7c-924f-f199fa3c5eb1', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "微民-住宿费-{EXP_LEVEL}IN[1] AND {ER_EXP_FEE}>{ER_DAYS} *600"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("1"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='微民', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[2] AND {ER_EXP_FEE}>{ER_DAYS}*700', alertMessage='您的房费高于公司标准', ruleId='f9b17610-7917-4f71-b369-602224fdd20d', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "微民-住宿费-{EXP_LEVEL}IN[2] AND {ER_EXP_FEE}>{ER_DAYS}*700"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("2"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='微民', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[3] AND {ER_EXP_FEE}>{ER_DAYS}*800', alertMessage='您的房费高于公司标准', ruleId='128e621a-832a-4876-81c8-a5a9624b6ca7', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "微民-住宿费-{EXP_LEVEL}IN[3] AND {ER_EXP_FEE}>{ER_DAYS}*800"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("3"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='微民', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_LOCATION_COUNTRY}IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*140', alertMessage='您的补贴高于公司标准', ruleId='06d1afc9-4a0e-4ad6-b0b1-01af068997fe', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "微民-差旅补贴-{ER_LOCATION_COUNTRY}IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*140"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["city"] in ("中国"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的补贴高于公司标准 ");end'}TravelRule{companyName='微民', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_LOCATION_COUNTRY}NOT IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的补贴高于公司标准', ruleId='922d99ff-c5bc-4f26-a365-d8b6e8a9a999', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "微民-差旅补贴-{ER_LOCATION_COUNTRY}NOT IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*400"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["city"] not in ("中国"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的补贴高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[一般员工] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的房费高于公司标准', ruleId='7c170ce0-080e-499a-9046-0dc7d226b86c', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-住宿费-{EXP_LEVEL}IN[一般员工] AND {ER_EXP_FEE}>{ER_DAYS}*400"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("一般员工"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*300', alertMessage='您的房费高于公司标准', ruleId='6135e677-867b-41ed-8d00-7512b5ec5c2a', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-住宿费-{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*300"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("一般员工"),  data["city"] not in ("北京","上海","深圳"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总监] AND {ER_EXP_FEE}>{ER_DAYS}*550', alertMessage='您的房费高于公司标准', ruleId='636ebfda-6d78-4ec7-a441-234ff931fa57', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-住宿费-{EXP_LEVEL}IN[总监] AND {ER_EXP_FEE}>{ER_DAYS}*550"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("总监"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总监] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的房费高于公司标准', ruleId='b236a113-e547-4f65-9ddc-3b9549efa6ce', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-住宿费-{EXP_LEVEL}IN[总监] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*400"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("总监"),  data["city"] not in ("北京","上海","深圳"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*700', alertMessage='您的房费高于公司标准', ruleId='8bb7e480-bf94-4c24-a46e-963ae60bee7e', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-住宿费-{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*700"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("总裁"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*500', alertMessage='您的房费高于公司标准', ruleId='f74d0d7c-d31d-49d9-84ff-c0889bf37771', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-住宿费-{EXP_LEVEL}IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*500"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("总裁"),  data["city"] not in ("北京","上海","深圳"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾南', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_EXP_FEE}>{ER_DAYS}*80', alertMessage='您的补贴高于公司标准', ruleId='154866b0-fdc5-433f-9c3f-640e9a812564', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾南-差旅补贴-{ER_EXP_FEE}>{ER_DAYS}*80"when  $invoice : MatchInvoiceTravelRuleRequestDto(  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的补贴高于公司标准 ");end'}TravelRule{companyName='腾新', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*600', alertMessage='您的房费高于公司标准', ruleId='e4ece4c7-f9ca-46fc-bb7b-2a4443513daf', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾新-住宿费-{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*600"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] in ("总裁"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾新', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}NOT IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*500', alertMessage='您的房费高于公司标准', ruleId='51768055-8a13-4d44-9c61-e261bcb74149', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾新-住宿费-{EXP_LEVEL}NOT IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*500"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] not in ("总裁"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾新', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的房费高于公司标准', ruleId='0d3f86b6-f937-4544-916d-8fac5061c479', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾新-住宿费-{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}>{ER_DAYS}*400"when  $invoice : MatchInvoiceTravelRuleRequestDto(  data["EXPENSE_LEVEL"] not in ("总裁"),  data["city"] not in ("北京","上海","深圳","成都","广州","杭州"),  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的房费高于公司标准 ");end'}TravelRule{companyName='腾新', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_EXP_FEE}>{ER_DAYS}*100', alertMessage='您的补贴高于公司标准', ruleId='a9c0f423-7880-4f86-a761-ba2f2ec83c66', droolsRule='package com.beaver.drools.exampl.travel.ruleimport java.math.*import com.beaver.drools.common.model.*rule  "腾新-差旅补贴-{ER_EXP_FEE}>{ER_DAYS}*100"when  $invoice : MatchInvoiceTravelRuleRequestDto(  BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"]) ) then   $invoice.setResult(RuleResult.REJECT);   $invoice.setRemarkMessage("您的补贴高于公司标准 ");end'}Process finished with exit code 0

 每产生一个规则,都用drools引擎校验了一下,以防出错。


 上面只是对简单的规则如:
{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}>{ER_DAYS}*400 做了解析,用的是比较笨的解析和组装,复杂的或者本文是不是可以用

https://github.com/antlr/antlr4
https://github.com/antlr/stringtemplate4
http://freemarker.org
这些工具更简单呢,后面学习一下第一个工具,再试试。

本文代码地址:
https://github.com/sdcuike/drools-example/tree/2017-05-21/src/main/java/com/beaver/drools/exampl/travel/rule


原创粉丝点击