├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── jp │ │ └── nian │ │ └── rule │ │ ├── compare │ │ └── RuleCompare.java │ │ ├── condition │ │ └── RuleCondition.java │ │ ├── context │ │ └── Context.java │ │ ├── engine │ │ ├── DefaultRuleEngine.java │ │ ├── RuleEngine.java │ │ └── RuleEngineFactory.java │ │ └── vo │ │ ├── CriticalConditionEnum.java │ │ ├── Operation.java │ │ ├── Operator.java │ │ ├── Parameter.java │ │ ├── Rule.java │ │ └── TypeEnum.java └── resources │ ├── 规则引擎构思.png │ └── 规则引擎设计.png └── test └── java └── com └── jp └── nian └── rule └── engine ├── RuleTest1.java ├── RuleTest10.java ├── RuleTest2.java ├── RuleTest3.java ├── RuleTest4.java ├── RuleTest5.java ├── RuleTest6.java ├── RuleTest7.java ├── RuleTest8.java └── RuleTest9.java /README.md: -------------------------------------------------------------------------------- 1 | # Java 规则引擎 实现 2 | > 规则引擎,纯属兴趣研究 3 | 4 | ###### @TODO,目标 5 | - 规则可以动态新增、修改,落地于DB 6 | - 规则包括用户的多个输入参数、运算符、运算(条件) 7 | 8 | ###### @DONE 测试类在src/test/java下 9 | - 目前完成条件测试----如果用户输入名称为tanfan,则返回success,否则返回fail。 10 | - RuleTest1.java 11 | - 目前完成条件测试----如果用户输入名称为tanfan或者niange或者呵呵,则返回success,否则返回fail。 12 | - RuleTest2.java 13 | - 目前完成条件测试----如果用户输入名称为tanfan,并且年龄为20,则返回success,否则返回fail。 14 | - RuleTest3.java 15 | - 目前完成条件测试----如果用户输入名称为tanfan,并且年龄小于20,则返回success,否则返回fail。 16 | - RuleTest4.java 17 | - 目前完成条件测试----如果用户输入名称输入偶数时,则返回success,否则返回fail。 18 | - RuleTest5.java 19 | - 目前完成条件测试----如果用户输入第一个数与第二个数相加等于5,则返回success,否则返回fail。 20 | - RuleTest6.java 21 | - 目前完成条件测试----如果用户购买商品满100元,那么商品价格打9折,否则不打折。 22 | - RuleTest7.java 23 | - 目前完成条件测试----如果用户购买的商品满100元,那么打9折;满150,打8.5折,满200以上打8折 24 | - RuleTest8.java 25 | - 目前完成条件测试----如果用户购买的商品满80,减5;满130减8;满170以上减10 26 | - RuleTest9.java 27 | - 目前完成条件测试----如果用户购买的商品满300,则赠品一个;满500,赠品两个 28 | - RuleTest10.java 29 | 30 | ###### @DOING 测试类在src/test/java下 31 | - 如果用户购买的商品满300,则赠品一个;满500,赠品两个 32 | 33 | ###### @TODO,还可以继续完善的条件(实际生活中的例子,电商活动经常有的) 34 | - 如果用户购买的商品满100元,那么打9折;满150,打8.5折,满200以上打8折 (满折) 35 | - 如果用户购买的商品满80,减5;满130减8;满170以上减10 (满减) 36 | - 如果用户购买的商品满300,则赠品一个;满500,赠品两个 (满赠) 37 | - 以上活动满足条件可以同时参与 38 | - 支持规则存放在DB 39 | - 支持从DB/文件获取规则 40 | 41 | ###### 规则引擎构思图: 42 | ![规则引擎构思](https://github.com/linian365boy/rule-core/blob/master/src/main/resources/%E8%A7%84%E5%88%99%E5%BC%95%E6%93%8E%E6%9E%84%E6%80%9D.png) 43 | ![规则引擎设计](https://github.com/linian365boy/rule-core/blob/master/src/main/resources/%E8%A7%84%E5%88%99%E5%BC%95%E6%93%8E%E8%AE%BE%E8%AE%A1.png) 44 | --- 45 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.jp.nian.rule 6 | rule-core 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | rule-core 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | org.apache.commons 20 | commons-lang3 21 | 3.2.1 22 | 23 | 24 | junit 25 | junit 26 | 4.10 27 | test 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/compare/RuleCompare.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.compare; 2 | 3 | import java.util.Comparator; 4 | 5 | public class RuleCompare implements Comparator { 6 | 7 | @Override 8 | public int compare(T t1, T t2) { 9 | if(t1==t2) return 0; 10 | if(t1 instanceof Long){ 11 | Long l1 = (Long)t1; 12 | Long l2 = (Long)t2; 13 | return Long.compare(l1, l2); 14 | }else if(t1 instanceof String){ 15 | String s1 = (String)t1; 16 | String s2 = (String)t2; 17 | return s1.compareTo(s2); 18 | }else if(t1 instanceof Double){ 19 | Double d1 = (Double)t1; 20 | Double d2 = (Double)t2; 21 | return Double.compare(d1, d2); 22 | } 23 | return 0; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/condition/RuleCondition.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.condition; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.apache.commons.lang3.builder.ToStringBuilder; 7 | import org.apache.commons.lang3.builder.ToStringStyle; 8 | 9 | import com.jp.nian.rule.vo.Operation; 10 | import com.jp.nian.rule.vo.Operator; 11 | 12 | /** 13 | * @ClassName: RuleCondition 14 | * @Description: 组合规则引擎的多条件,(或、与) 15 | * @date: 2017年7月26日 下午6:34:57 16 | * 17 | * @author tanfan 18 | * @version 19 | * @since JDK 1.7 20 | */ 21 | public class RuleCondition { 22 | /** 23 | * 数组List存放运算 24 | */ 25 | private List operations = new ArrayList<>(); 26 | 27 | /** 28 | * and:构造and节点 29 | * @author tanfan 30 | * @param operation 31 | * @return 32 | * @since JDK 1.7 33 | */ 34 | public RuleCondition and(Operation operation) { 35 | if(operations.size() > 0){ 36 | Operation lastOperation = operations.get(operations.size()-1); 37 | lastOperation.setNextOperator(Operator.And); 38 | lastOperation.setNextOperation(operation); 39 | } 40 | operations.add(operation); 41 | return this; 42 | } 43 | 44 | /** 45 | * and:构造or节点 46 | * @author tanfan 47 | * @param operation 48 | * @return 49 | * @since JDK 1.7 50 | */ 51 | public RuleCondition or(Operation operation) { 52 | Operation lastOperation = operations.get(operations.size()-1); 53 | lastOperation.setNextOperator(Operator.Or); 54 | lastOperation.setNextOperation(operation); 55 | operations.add(operation); 56 | return this; 57 | } 58 | 59 | /** 60 | * exclude:构造exclude排斥节点 61 | * @author tanfan 62 | * @param operation2 63 | * @return 64 | * @since JDK 1.7 65 | */ 66 | public RuleCondition exclude(Operation operation) { 67 | Operation lastOperation = operations.get(operations.size()-1); 68 | lastOperation.setNextOperator(Operator.Ex); 69 | lastOperation.setNextOperation(operation); 70 | operations.add(operation); 71 | return this; 72 | } 73 | 74 | public List getOperations() { 75 | return operations; 76 | } 77 | 78 | public void setOperations(List operations) { 79 | this.operations = operations; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/context/Context.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.context; 2 | 3 | import com.jp.nian.rule.vo.Rule; 4 | 5 | /** 6 | * @ClassName: Context 7 | * @Description: 模拟上下文 8 | * @date: 2017年7月26日 下午3:00:42 9 | * 10 | * @author tanfan 11 | * @version 12 | * @since JDK 1.7 13 | */ 14 | public class Context { 15 | 16 | private static ThreadLocal ruleLocal = new ThreadLocal(){ 17 | protected Rule initialValue() { 18 | return null; 19 | }; 20 | }; 21 | 22 | public static void setRule(Rule value){ 23 | ruleLocal.set(value); 24 | } 25 | 26 | public static Rule getRule(){ 27 | return ruleLocal.get(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/engine/DefaultRuleEngine.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | import org.apache.commons.lang3.time.DateUtils; 7 | 8 | import com.jp.nian.rule.compare.RuleCompare; 9 | import com.jp.nian.rule.condition.RuleCondition; 10 | import com.jp.nian.rule.context.Context; 11 | import com.jp.nian.rule.vo.CriticalConditionEnum; 12 | import com.jp.nian.rule.vo.Operation; 13 | import com.jp.nian.rule.vo.Operator; 14 | import com.jp.nian.rule.vo.Parameter; 15 | import com.jp.nian.rule.vo.Rule; 16 | import com.jp.nian.rule.vo.TypeEnum; 17 | 18 | /** 19 | * @ClassName: DefaultRuleEngine 20 | * @Description: 实现默认的规则引擎 21 | * @date: 2016年7月6日 下午6:02:47 22 | * 23 | * @author tanfan 24 | * @version 25 | * @since JDK 1.7 26 | */ 27 | public class DefaultRuleEngine extends RuleEngine { 28 | public DefaultRuleEngine() {} 29 | 30 | @Override 31 | public Object execute() throws Exception { 32 | Rule rule = Context.getRule(); 33 | Operation operation = compute(rule); 34 | if(operation != null){ 35 | if(operation.getExpectVal() != null){ 36 | return operation.getExpectVal(); 37 | }else{ 38 | return rule.getTrueValue(); 39 | } 40 | } 41 | return rule.getFalseValue(); 42 | } 43 | 44 | /** 45 | * computeReturnOperation:返回符合条件的那个运算 46 | * @author tanfan 47 | * @param rule 48 | * @return 49 | * @throws Exception 50 | * @since JDK 1.7 51 | */ 52 | private Operation compute(Rule rule) throws Exception { 53 | RuleCondition condition = rule.getCondition(); 54 | List operations = condition.getOperations(); 55 | Operation resultOper = null; 56 | for(Operation oper : operations){ 57 | boolean flag = compare(oper); 58 | if(flag){ 59 | if(oper.getNextOperator() == Operator.And){ 60 | continue; 61 | }else if(oper.getNextOperator() == Operator.Ex){ 62 | resultOper = oper; 63 | break; 64 | } 65 | }else{ 66 | if(oper.getNextOperator() == Operator.Or || 67 | oper.getNextOperator() == Operator.Ex){ 68 | continue; 69 | } 70 | } 71 | if(flag){ 72 | resultOper = oper; 73 | } 74 | break; 75 | } 76 | return resultOper; 77 | } 78 | 79 | private boolean compare(Operation operation) throws Exception { 80 | Parameter param = operation.getParam(); 81 | //临界值,真实类型,用作比较。比如年龄,应该是数值类型;姓名,应该是字符串类型。 82 | if(operation.getCriticalType() == CriticalConditionEnum.Operation){ 83 | return operation.isCriticalOperation(); 84 | }else{ 85 | Object value = getValue(param.getType(), operation.getCriticalValue()); 86 | Object objVal = getValue(param.getType(), param.getValue()); 87 | int result = Objects.compare(objVal, value, new RuleCompare<>()); 88 | switch(operation.getOperator()){ 89 | case Eq: 90 | return result == 0; 91 | case GreaterThan: 92 | return result > 0; 93 | case LessThan: 94 | return result < 0; 95 | case GreaterThanEq: 96 | return result >= 0; 97 | case LessThanEq: 98 | return result <= 0; 99 | default: 100 | return false; 101 | } 102 | } 103 | } 104 | 105 | 106 | private Object getValue(TypeEnum type, String val) throws Exception { 107 | switch(type){ 108 | case Long: return Long.parseLong(val); 109 | case Double: return Double.parseDouble(val); 110 | case Date: return DateUtils.parseDate(val, "yyyy-MM-dd hh:mm:ss").getTime(); 111 | default: return val; 112 | } 113 | } 114 | 115 | @Override 116 | public RuleEngine loadRule(Rule rule) { 117 | Context.setRule(rule); 118 | return this; 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/engine/RuleEngine.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import com.jp.nian.rule.vo.Rule; 4 | 5 | /** 6 | * @ClassName: RuleEngine 7 | * @Description: 抽象规则引擎 8 | * @date: 2016年7月6日 下午2:22:40 9 | * 10 | * @author tanfan 11 | * @version 12 | * @since JDK 1.7 13 | */ 14 | public abstract class RuleEngine { 15 | /** 16 | * loadRule:加载规则 17 | * @author tanfan 18 | * @param oper 19 | * @since JDK 1.7 20 | */ 21 | public abstract RuleEngine loadRule(Rule rule); 22 | /** 23 | * execute:根据条件执行规则 24 | * @author tanfan 25 | * @param 26 | * @since JDK 1.7 27 | * @return T 返回值 28 | */ 29 | public abstract Object execute() throws Exception; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/engine/RuleEngineFactory.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.io.ObjectStreamException; 4 | import java.io.Serializable; 5 | 6 | /** 7 | * @ClassName: RuleEngineFactory 8 | * @Description: 静态内部类实现单例工厂 9 | * @date: 2016年7月6日 下午5:58:34 10 | * 11 | * @author tanfan 12 | * @version 13 | * @since JDK 1.7 14 | */ 15 | public class RuleEngineFactory implements Serializable { 16 | /** 17 | * serialVersionUID:序列化 18 | * @since JDK 1.7 19 | */ 20 | private static final long serialVersionUID = -9014631908354445743L; 21 | 22 | private RuleEngineFactory(){} 23 | 24 | //静态内部类 25 | private static class RuleEngineFactoryInner{ 26 | private static RuleEngineFactory instance = new RuleEngineFactory(); 27 | } 28 | 29 | public static RuleEngineFactory newInstance() { 30 | return RuleEngineFactoryInner.instance; 31 | } 32 | 33 | public RuleEngine getRuleEngine() { 34 | return new DefaultRuleEngine(); 35 | } 36 | 37 | /** 38 | * 反序列化单例需要 ,在反序列化时会被调用,若不加此方法 则反序列化的类不是单例的 39 | */ 40 | private Object readResolve() throws ObjectStreamException { 41 | return newInstance(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/vo/CriticalConditionEnum.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.vo; 2 | 3 | public enum CriticalConditionEnum { 4 | 5 | Operation("operation","运算"), 6 | Equal("equal","默认的临界条件"); 7 | 8 | private String name; 9 | private String comment; 10 | 11 | private CriticalConditionEnum(String name, String comment){ 12 | this.name = name; 13 | this.comment = comment; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public String getComment() { 25 | return comment; 26 | } 27 | 28 | public void setComment(String comment) { 29 | this.comment = comment; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/vo/Operation.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.vo; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | import org.apache.commons.lang3.builder.ToStringStyle; 5 | 6 | /** 7 | * @ClassName: Operation 8 | * @Description: 运算,是需要包括运算符与参数的 9 | * @date: 2017年7月26日 下午12:31:47 10 | * 11 | * @author tanfan 12 | * @version 13 | * @since JDK 1.7 14 | */ 15 | public class Operation { 16 | /** 17 | * 参数 18 | */ 19 | private Parameter param; 20 | /** 21 | * 运算符 22 | */ 23 | private Operator operator; 24 | /** 25 | * 临界值,类型是param的参数类型 26 | */ 27 | private String criticalValue; 28 | /** 29 | * 与下一个运算的运算符 30 | */ 31 | private Operator nextOperator; 32 | /** 33 | * 下一个运算 34 | */ 35 | private Operation nextOperation; 36 | /** 37 | * 临界运算 38 | */ 39 | private boolean criticalOperation; 40 | /** 41 | * 临界的条件类型,默认是Equal 42 | */ 43 | private CriticalConditionEnum criticalType = CriticalConditionEnum.Equal; 44 | /** 45 | * 多个条件满足时,根据优先级进行哪个条件运算 46 | * 不设值,按添加顺序运算条件 47 | * 该值越大,优先权越大 48 | */ 49 | private int priority; 50 | /** 51 | * 运算期望的返回值,按道理,每个运算都会有一个期望的返回值 52 | * 优先权大于Rule类的trueValue 53 | * 如果有值,会先返回该值 54 | */ 55 | private Object expectVal; 56 | 57 | public Parameter getParam() { 58 | return param; 59 | } 60 | 61 | public void setParam(Parameter param) { 62 | this.param = param; 63 | } 64 | public Operator getOperator() { 65 | return operator; 66 | } 67 | public void setOperator(Operator operator) { 68 | this.operator = operator; 69 | } 70 | 71 | public String getCriticalValue() { 72 | return criticalValue; 73 | } 74 | 75 | public void setCriticalValue(String criticalValue) { 76 | this.criticalValue = criticalValue; 77 | } 78 | 79 | public Operator getNextOperator() { 80 | return nextOperator; 81 | } 82 | 83 | public void setNextOperator(Operator nextOperator) { 84 | this.nextOperator = nextOperator; 85 | } 86 | 87 | public void setNextOperation(Operation operation) { 88 | this.nextOperation = operation; 89 | } 90 | 91 | public Operation getNextOperation() { 92 | return nextOperation; 93 | } 94 | 95 | public boolean isCriticalOperation() { 96 | return criticalOperation; 97 | } 98 | 99 | public void setCriticalOperation(boolean criticalOperation) { 100 | this.criticalOperation = criticalOperation; 101 | } 102 | 103 | public CriticalConditionEnum getCriticalType() { 104 | return criticalType; 105 | } 106 | 107 | public void setCriticalType(CriticalConditionEnum criticalType) { 108 | this.criticalType = criticalType; 109 | } 110 | 111 | public int getPriority() { 112 | return priority; 113 | } 114 | 115 | public void setPriority(int priority) { 116 | this.priority = priority; 117 | } 118 | 119 | public Object getExpectVal() { 120 | return expectVal; 121 | } 122 | 123 | public void setExpectVal(Object expectVal) { 124 | this.expectVal = expectVal; 125 | } 126 | 127 | @Override 128 | public String toString() { 129 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/vo/Operator.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.vo; 2 | 3 | /** 4 | * @ClassName: Operation 5 | * @Description: 规则之间需要用到的一些运算符 6 | * @date: 2016年7月8日 上午10:22:53 7 | * 8 | * @author tanfan 9 | * @version 10 | * @since JDK 1.7 11 | */ 12 | public enum Operator { 13 | 14 | Eq("eq","="), 15 | GreaterThan("greaterThan",">"), 16 | LessThan("lessThan","<"), 17 | GreaterThanEq("greaterThanEq",">="), 18 | LessThanEq("lessThanEq","<="), 19 | 20 | /** 21 | * 与 22 | */ 23 | And("and","&"), 24 | /** 25 | * 或 26 | */ 27 | Or("or","|"), 28 | /** 29 | * 非 30 | */ 31 | Ex("exclude","!"); 32 | 33 | 34 | /** 35 | * 名称 36 | */ 37 | private String name; 38 | /** 39 | * 备注 40 | */ 41 | private String comment; 42 | 43 | private Operator(String name, String comment){ 44 | this.name = name; 45 | this.comment = comment; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | public void setName(String name) { 52 | this.name = name; 53 | } 54 | public String getComment() { 55 | return comment; 56 | } 57 | public void setComment(String comment) { 58 | this.comment = comment; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/vo/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.vo; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.apache.commons.lang3.builder.ToStringBuilder; 6 | import org.apache.commons.lang3.builder.ToStringStyle; 7 | 8 | /** 9 | * @ClassName: Parameter 10 | * @Description: 用户输入的参数 11 | * @date: 2017年7月26日 上午11:44:17 12 | * 13 | * @author tanfan 14 | * @version 15 | * @since JDK 1.7 16 | */ 17 | public class Parameter implements Serializable { 18 | /** 19 | * serialVersionUID:序列化 20 | * @since JDK 1.7 21 | */ 22 | private static final long serialVersionUID = -2996445759006867398L; 23 | /** 24 | * 参数名称 25 | */ 26 | private String name; 27 | /** 28 | * 参数类型 29 | */ 30 | private TypeEnum type; 31 | /** 32 | * 参数中文描述 33 | */ 34 | private String cnName; 35 | /** 36 | * 参数值 37 | */ 38 | private String value; 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | public void setName(String name) { 44 | this.name = name; 45 | } 46 | public TypeEnum getType() { 47 | return type; 48 | } 49 | public void setType(TypeEnum type) { 50 | this.type = type; 51 | } 52 | public String getCnName() { 53 | return cnName; 54 | } 55 | public void setCnName(String cnName) { 56 | this.cnName = cnName; 57 | } 58 | public String getValue() { 59 | return value; 60 | } 61 | public void setValue(String value) { 62 | this.value = value; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/vo/Rule.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.vo; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import org.apache.commons.lang3.builder.ToStringBuilder; 8 | import org.apache.commons.lang3.builder.ToStringStyle; 9 | 10 | import com.jp.nian.rule.condition.RuleCondition; 11 | 12 | public class Rule implements Serializable { 13 | /** 14 | * serialVersionUID:序列化 15 | * @since JDK 1.7 16 | */ 17 | private static final long serialVersionUID = 9086287116677139111L; 18 | //规则名称 19 | private String name; 20 | //规则创建日期 21 | private Date createDate; 22 | //入参 23 | private List inputParams; 24 | //实际出参类型 25 | private TypeEnum outputType; 26 | /** 27 | * True分支的结果 28 | */ 29 | private String trueValue; 30 | /** 31 | * False分支的结果 32 | */ 33 | private String falseValue; 34 | /** 35 | * 规则条件组合 36 | */ 37 | private RuleCondition condition = new RuleCondition(); 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | public Date getCreateDate() { 46 | return createDate; 47 | } 48 | public void setCreateDate(Date createDate) { 49 | this.createDate = createDate; 50 | } 51 | public List getInputParams() { 52 | return inputParams; 53 | } 54 | public void setInputParams(List inputParams) { 55 | this.inputParams = inputParams; 56 | } 57 | public TypeEnum getOutputType() { 58 | return outputType; 59 | } 60 | public void setOutputType(TypeEnum outputType) { 61 | this.outputType = outputType; 62 | } 63 | public String getTrueValue() { 64 | return trueValue; 65 | } 66 | public void setTrueValue(String trueValue) { 67 | this.trueValue = trueValue; 68 | } 69 | public String getFalseValue() { 70 | return falseValue; 71 | } 72 | public void setFalseValue(String falseValue) { 73 | this.falseValue = falseValue; 74 | } 75 | 76 | public RuleCondition getCondition() { 77 | return condition; 78 | } 79 | public void setCondition(RuleCondition condition) { 80 | this.condition = condition; 81 | } 82 | 83 | public RuleCondition setOperation(Operation operation) { 84 | //设置第一个条件 85 | return condition.and(operation); 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/jp/nian/rule/vo/TypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.vo; 2 | 3 | /** 4 | * @ClassName: TypeEnum 5 | * @Description: 类型枚举 6 | * @date: 2017年7月28日 下午12:51:17 7 | * 8 | * @author tanfan 9 | * @version 10 | * @since JDK 1.7 11 | */ 12 | public enum TypeEnum { 13 | 14 | Long("long","长整形"), 15 | Double("double","浮点型"), 16 | String("string","字符串"), 17 | Date("date","日期"); 18 | 19 | private String typeName; 20 | private String comment; 21 | 22 | private TypeEnum(String typeName, String comment){ 23 | this.typeName = typeName; 24 | this.comment = comment; 25 | } 26 | 27 | public String getTypeName() { 28 | return typeName; 29 | } 30 | 31 | public void setTypeName(String typeName) { 32 | this.typeName = typeName; 33 | } 34 | 35 | public String getComment() { 36 | return comment; 37 | } 38 | 39 | public void setComment(String comment) { 40 | this.comment = comment; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/resources/规则引擎构思.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linian365boy/rule-core/772f6a66492ad853608418679bef5febac3a3680/src/main/resources/规则引擎构思.png -------------------------------------------------------------------------------- /src/main/resources/规则引擎设计.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linian365boy/rule-core/772f6a66492ad853608418679bef5febac3a3680/src/main/resources/规则引擎设计.png -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest1.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Operator; 8 | import com.jp.nian.rule.vo.Parameter; 9 | import com.jp.nian.rule.vo.Rule; 10 | import com.jp.nian.rule.vo.TypeEnum; 11 | 12 | public class RuleTest1 { 13 | 14 | /** 15 | * main:有规则 16 | * 如果用户输入名称为tanfan,则返回success,否则返回fail。 17 | * 测试1:用户输入nima,期望输出fail 18 | * 测试2:用户输入tanfan,期望输出success 19 | * @author tanfan 20 | * @param args 21 | * @since JDK 1.7 22 | */ 23 | public static void main(String[] args) throws Exception { 24 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 25 | Parameter inputParam = new Parameter(); 26 | inputParam.setName("name"); 27 | inputParam.setCnName("名称"); 28 | inputParam.setType(TypeEnum.String); 29 | inputParam.setValue("tanfan"); 30 | 31 | Rule rule = new Rule(); 32 | rule.setInputParams(Arrays.asList(inputParam)); 33 | rule.setName("第一个规则例子"); 34 | rule.setCreateDate(new Date()); 35 | 36 | Operation operation = new Operation(); 37 | operation.setOperator(Operator.Eq); 38 | operation.setParam(inputParam); 39 | operation.setCriticalValue("tanfan"); 40 | //优先权大于Rule trueValue 41 | operation.setExpectVal("tanfan"); 42 | 43 | rule.setOperation(operation); 44 | rule.setOutputType(TypeEnum.String); 45 | rule.setFalseValue("fail"); 46 | rule.setTrueValue("success"); 47 | 48 | Object strResult = engine.loadRule(rule).execute(); 49 | System.out.println("the result is "+strResult); 50 | System.out.println("the rule info is "+ rule); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest10.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import com.jp.nian.rule.vo.CriticalConditionEnum; 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Parameter; 8 | import com.jp.nian.rule.vo.Rule; 9 | import com.jp.nian.rule.vo.TypeEnum; 10 | 11 | public class RuleTest10 { 12 | 13 | /** 14 | * main:有规则 15 | * 如果用户购买的商品满300,则赠品一个;满500,赠品两个 16 | * 测试1:购买商品310元,期望输出赠品一个(生产中,订单服务应该去获取一个赠品的id,并为该用户下单) 17 | * 测试2:用户输入501元,期望输出赠品两个(生产中,订单服务应该去获取一个赠品的id,并为该用户下单) 18 | * 测试3:用户输入200元,期望输出没有赠品 19 | * @author tanfan 20 | * @param args 21 | * @since JDK 1.7 22 | */ 23 | public static void main(String[] args) throws Exception { 24 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 25 | 26 | /** 模拟用户的输入 start **/ 27 | Parameter inputParam = new Parameter(); 28 | inputParam.setName("price"); 29 | inputParam.setCnName("价格"); 30 | inputParam.setType(TypeEnum.Double); 31 | inputParam.setValue("200"); 32 | /** 用户的输入 end **/ 33 | 34 | /** 需要满足的运算条件 start **/ 35 | Operation operation = new Operation(); 36 | /** 设置临界条件为运算**/ 37 | operation.setCriticalType(CriticalConditionEnum.Operation); 38 | /** 设置临界条件的运算**/ 39 | operation.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=300); 40 | operation.setPriority(1); 41 | operation.setExpectVal("赠品一个"); 42 | 43 | Operation operation2 = new Operation(); 44 | operation2.setCriticalType(CriticalConditionEnum.Operation); 45 | operation2.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=500); 46 | operation2.setPriority(2); 47 | operation2.setExpectVal("赠品两个"); 48 | /** 需要满足的条件 end **/ 49 | 50 | Rule rule = new Rule(); 51 | rule.setInputParams(Arrays.asList(inputParam)); 52 | rule.setName("第十个规则例子"); 53 | rule.setCreateDate(new Date()); 54 | /** 需要根据前端输入的优先值,进行先后顺序绑定,高优先值,放在第一个 **/ 55 | rule.setOperation(operation2).exclude(operation); 56 | rule.setOutputType(TypeEnum.Double); 57 | /** 设置不满足条件返回值 **/ 58 | rule.setFalseValue("没有赠品"); 59 | 60 | Object strResult = engine.loadRule(rule).execute(); 61 | System.out.println("the result is "+strResult); 62 | System.out.println("the rule info is "+ rule); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest2.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Operator; 8 | import com.jp.nian.rule.vo.Parameter; 9 | import com.jp.nian.rule.vo.Rule; 10 | import com.jp.nian.rule.vo.TypeEnum; 11 | 12 | public class RuleTest2 { 13 | 14 | /** 15 | * main:有规则 16 | * 如果用户输入名称为tanfan或者niange或者呵呵,则返回success,否则返回fail。 17 | * 测试1:用户输入nima,期望输出fail 18 | * 测试2:用户输入tanfan,期望输出success 19 | * 测试3:用户输入niange,期望输出success 20 | * 测试4:用户输入呵呵,期望输出success 21 | * 测试5:用户输入呵呵da,期望输出fail 22 | * @author tanfan 23 | * @param args 24 | * @since JDK 1.7 25 | */ 26 | public static void main(String[] args) throws Exception { 27 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 28 | Parameter inputParam = new Parameter(); 29 | inputParam.setName("name"); 30 | inputParam.setCnName("名称"); 31 | inputParam.setType(TypeEnum.String); 32 | inputParam.setValue("呵呵"); 33 | 34 | Rule rule = new Rule(); 35 | rule.setInputParams(Arrays.asList(inputParam)); 36 | rule.setName("第二个规则例子"); 37 | rule.setCreateDate(new Date()); 38 | 39 | 40 | Operation operation = new Operation(); 41 | operation.setOperator(Operator.Eq); 42 | operation.setParam(inputParam); 43 | operation.setCriticalValue("tanfan"); 44 | 45 | Operation operation2 = new Operation(); 46 | operation2.setOperator(Operator.Eq); 47 | operation2.setParam(inputParam); 48 | operation2.setCriticalValue("niange"); 49 | 50 | Operation operation3 = new Operation(); 51 | operation3.setOperator(Operator.Eq); 52 | operation3.setParam(inputParam); 53 | operation3.setCriticalValue("呵呵"); 54 | 55 | rule.setOperation(operation).or(operation2).or(operation3); 56 | 57 | rule.setOutputType(TypeEnum.String); 58 | rule.setFalseValue("fail"); 59 | rule.setTrueValue("success"); 60 | 61 | Object strResult = engine.loadRule(rule).execute(); 62 | System.out.println("the result is "+strResult); 63 | System.out.println("the rule info is "+ rule); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest3.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Operator; 8 | import com.jp.nian.rule.vo.Parameter; 9 | import com.jp.nian.rule.vo.Rule; 10 | import com.jp.nian.rule.vo.TypeEnum; 11 | 12 | public class RuleTest3 { 13 | 14 | /** 15 | * main:有规则 16 | * 如果用户输入名称为tanfan,并且年龄为20,则返回success,否则返回fail。 17 | * 测试1:用户输入nima,20,期望输出fail 18 | * 测试2:用户输入tanfan,20,期望输出success 19 | * 测试3:用户输入nima,19,期望输出fail 20 | * 测试4:用户输入tanfan,19,期望输出fail 21 | * @author tanfan 22 | * @param args 23 | * @since JDK 1.7 24 | */ 25 | public static void main(String[] args) throws Exception { 26 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 27 | 28 | /** 用户的输入 start **/ 29 | Parameter inputParam = new Parameter(); 30 | inputParam.setName("name"); 31 | inputParam.setCnName("名称"); 32 | inputParam.setType(TypeEnum.String); 33 | inputParam.setValue("nima"); 34 | 35 | Parameter inputParam2 = new Parameter(); 36 | inputParam2.setName("age"); 37 | inputParam2.setCnName("年龄"); 38 | inputParam2.setType(TypeEnum.Long); 39 | inputParam2.setValue("20"); 40 | /** 用户的输入 end **/ 41 | 42 | /** 需要满足的条件 start **/ 43 | Operation operation = new Operation(); 44 | operation.setOperator(Operator.Eq); 45 | operation.setParam(inputParam); 46 | operation.setCriticalValue("tanfan"); 47 | 48 | Operation operation2 = new Operation(); 49 | operation2.setOperator(Operator.Eq); 50 | operation2.setParam(inputParam2); 51 | operation2.setCriticalValue("20"); 52 | /** 需要满足的条件 end **/ 53 | 54 | Rule rule = new Rule(); 55 | rule.setInputParams(Arrays.asList(inputParam,inputParam2)); 56 | rule.setName("第三个规则例子"); 57 | rule.setCreateDate(new Date()); 58 | rule.setOperation(operation).and(operation2); 59 | rule.setOutputType(TypeEnum.String); 60 | rule.setFalseValue("fail"); 61 | rule.setTrueValue("success"); 62 | 63 | Object strResult = engine.loadRule(rule).execute(); 64 | System.out.println("the result is "+strResult); 65 | System.out.println("the rule info is "+ rule); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest4.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Operator; 8 | import com.jp.nian.rule.vo.Parameter; 9 | import com.jp.nian.rule.vo.Rule; 10 | import com.jp.nian.rule.vo.TypeEnum; 11 | 12 | public class RuleTest4 { 13 | 14 | /** 15 | * main:有规则 16 | * 如果用户输入名称为tanfan,并且输入年龄小于20时,则返回success,否则返回fail。 17 | * 测试1:用户输入nima,20,期望输出fail 18 | * 测试2:用户输入tanfan,20,期望输出fail 19 | * 测试3:用户输入nima,19,期望输出fail 20 | * 测试4:用户输入tanfan,19,期望输出success 21 | * @author tanfan 22 | * @param args 23 | * @since JDK 1.7 24 | */ 25 | public static void main(String[] args) throws Exception { 26 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 27 | 28 | /** 用户的输入 start **/ 29 | Parameter inputParam = new Parameter(); 30 | inputParam.setName("name"); 31 | inputParam.setCnName("名称"); 32 | inputParam.setType(TypeEnum.String); 33 | inputParam.setValue("tanfan"); 34 | 35 | Parameter inputParam2 = new Parameter(); 36 | inputParam2.setName("age"); 37 | inputParam2.setCnName("年龄"); 38 | inputParam2.setType(TypeEnum.Long); 39 | inputParam2.setValue("29"); 40 | /** 用户的输入 end **/ 41 | 42 | /** 需要满足的条件 start **/ 43 | Operation operation = new Operation(); 44 | operation.setOperator(Operator.Eq); 45 | operation.setParam(inputParam); 46 | operation.setCriticalValue("tanfan"); 47 | 48 | Operation operation2 = new Operation(); 49 | operation2.setOperator(Operator.LessThan); 50 | operation2.setParam(inputParam2); 51 | operation2.setCriticalValue("20"); 52 | /** 需要满足的条件 end **/ 53 | 54 | Rule rule = new Rule(); 55 | rule.setInputParams(Arrays.asList(inputParam,inputParam2)); 56 | rule.setName("第四个规则例子"); 57 | rule.setCreateDate(new Date()); 58 | rule.setOperation(operation).and(operation2); 59 | rule.setOutputType(TypeEnum.String); 60 | rule.setFalseValue("fail"); 61 | rule.setTrueValue("success"); 62 | 63 | Object strResult = engine.loadRule(rule).execute(); 64 | System.out.println("the result is "+strResult); 65 | System.out.println("the rule info is "+ rule); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest5.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import com.jp.nian.rule.vo.CriticalConditionEnum; 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Parameter; 8 | import com.jp.nian.rule.vo.Rule; 9 | import com.jp.nian.rule.vo.TypeEnum; 10 | 11 | public class RuleTest5 { 12 | 13 | /** 14 | * main:有规则 15 | * 如果用户输入名称输入偶数时,则返回success,否则返回fail。 16 | * 测试1:用户输入0,期望输出success 17 | * 测试2:用户输入1,期望输出fail 18 | * 测试3:用户输入2,期望输出success 19 | * 测试4:用户输入3,期望输出fail 20 | * @author tanfan 21 | * @param args 22 | * @since JDK 1.7 23 | */ 24 | public static void main(String[] args) throws Exception { 25 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 26 | 27 | /** 模拟用户的输入 start **/ 28 | Parameter inputParam = new Parameter(); 29 | inputParam.setName("number"); 30 | inputParam.setCnName("数字"); 31 | inputParam.setType(TypeEnum.Long); 32 | inputParam.setValue("5"); 33 | /** 用户的输入 end **/ 34 | 35 | /** 需要满足的条件 start **/ 36 | Operation operation = new Operation(); 37 | operation.setParam(inputParam); 38 | operation.setCriticalType(CriticalConditionEnum.Operation); 39 | operation.setCriticalOperation(Long.parseLong(inputParam.getValue())%2 == 0); 40 | /** 需要满足的条件 end **/ 41 | 42 | Rule rule = new Rule(); 43 | rule.setInputParams(Arrays.asList(inputParam)); 44 | rule.setName("第五个规则例子"); 45 | rule.setCreateDate(new Date()); 46 | rule.setOperation(operation); 47 | rule.setOutputType(TypeEnum.String); 48 | rule.setFalseValue("fail"); 49 | rule.setTrueValue("success"); 50 | 51 | Object strResult = engine.loadRule(rule).execute(); 52 | System.out.println("the result is "+strResult); 53 | System.out.println("the rule info is "+ rule); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest6.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import com.jp.nian.rule.vo.CriticalConditionEnum; 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Parameter; 8 | import com.jp.nian.rule.vo.Rule; 9 | import com.jp.nian.rule.vo.TypeEnum; 10 | 11 | public class RuleTest6 { 12 | 13 | /** 14 | * main:有规则 15 | * 如果用户输入第一个数与第二个数相加等于5,则返回success,否则返回fail。 16 | * 测试1:用户输入0,1,期望输出fail 17 | * 测试2:用户输入2,3,期望输出success 18 | * 测试3:用户输入3,2,期望输出success 19 | * 测试4:用户输入4,1,期望输出success 20 | * 测试5:用户输入5,0,期望输出success 21 | * 测试6:用户输入2,2,期望输出fail 22 | * @author tanfan 23 | * @param args 24 | * @since JDK 1.7 25 | */ 26 | public static void main(String[] args) throws Exception { 27 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 28 | 29 | /** 模拟用户的输入 start **/ 30 | Parameter inputParam = new Parameter(); 31 | inputParam.setName("number1"); 32 | inputParam.setCnName("数字1"); 33 | inputParam.setType(TypeEnum.Long); 34 | inputParam.setValue("2"); 35 | 36 | Parameter inputParam2 = new Parameter(); 37 | inputParam2.setName("number2"); 38 | inputParam2.setCnName("数字2"); 39 | inputParam2.setType(TypeEnum.Long); 40 | inputParam2.setValue("3"); 41 | /** 用户的输入 end **/ 42 | 43 | /** 需要满足的条件 start **/ 44 | Operation operation = new Operation(); 45 | operation.setCriticalType(CriticalConditionEnum.Operation); 46 | operation.setCriticalOperation(Long.parseLong(inputParam.getValue())+Long.parseLong(inputParam2.getValue()) == 5); 47 | /** 需要满足的条件 end **/ 48 | 49 | Rule rule = new Rule(); 50 | rule.setInputParams(Arrays.asList(inputParam)); 51 | rule.setName("第六个规则例子"); 52 | rule.setCreateDate(new Date()); 53 | rule.setOperation(operation); 54 | rule.setOutputType(TypeEnum.String); 55 | rule.setFalseValue("fail"); 56 | rule.setTrueValue("success"); 57 | 58 | Object strResult = engine.loadRule(rule).execute(); 59 | System.out.println("the result is "+strResult); 60 | System.out.println("the rule info is "+ rule); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest7.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import com.jp.nian.rule.vo.CriticalConditionEnum; 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Parameter; 8 | import com.jp.nian.rule.vo.Rule; 9 | import com.jp.nian.rule.vo.TypeEnum; 10 | 11 | public class RuleTest7 { 12 | 13 | /** 14 | * main:有规则 15 | * 如果用户购买商品满100元,那么商品价格打9折,否则不打折。 16 | * 测试1:购买商品190元,期望输出190*90% 17 | * 测试2:用户输入90元,期望输出90 18 | * 测试3:用户输入100元,期望输出100*90% 19 | * @author tanfan 20 | * @param args 21 | * @since JDK 1.7 22 | */ 23 | public static void main(String[] args) throws Exception { 24 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 25 | 26 | /** 模拟用户的输入 start **/ 27 | Parameter inputParam = new Parameter(); 28 | inputParam.setName("price"); 29 | inputParam.setCnName("价格"); 30 | inputParam.setType(TypeEnum.Double); 31 | inputParam.setValue("90"); 32 | /** 用户的输入 end **/ 33 | 34 | /** 需要满足的条件 start **/ 35 | Operation operation = new Operation(); 36 | operation.setCriticalType(CriticalConditionEnum.Operation); 37 | operation.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=100); 38 | /** 需要满足的条件 end **/ 39 | 40 | Rule rule = new Rule(); 41 | rule.setInputParams(Arrays.asList(inputParam)); 42 | rule.setName("第七个规则例子"); 43 | rule.setCreateDate(new Date()); 44 | rule.setOperation(operation); 45 | rule.setOutputType(TypeEnum.Double); 46 | /** 设置不满足条件返回值 **/ 47 | rule.setFalseValue(String.valueOf(Double.parseDouble(inputParam.getValue()))); 48 | /** 设置满足条件返回值 **/ 49 | rule.setTrueValue(String.valueOf(Double.parseDouble(inputParam.getValue())*0.9)); 50 | 51 | Object strResult = engine.loadRule(rule).execute(); 52 | System.out.println("the result is "+strResult); 53 | System.out.println("the rule info is "+ rule); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest8.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import com.jp.nian.rule.vo.CriticalConditionEnum; 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Parameter; 8 | import com.jp.nian.rule.vo.Rule; 9 | import com.jp.nian.rule.vo.TypeEnum; 10 | 11 | public class RuleTest8 { 12 | 13 | /** 14 | * main:有规则 15 | * 如果用户购买的商品满100元,那么打9折;满150,打8.5折,满200以上打8折。 16 | * 测试1:购买商品110元,期望输出110*90% 17 | * 测试2:用户输入190元,期望输出190*85% 18 | * 测试3:用户输入200元,期望输出200*80% 19 | * 测试4:用户输入80元,期望输出80 20 | * @author tanfan 21 | * @param args 22 | * @since JDK 1.7 23 | */ 24 | public static void main(String[] args) throws Exception { 25 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 26 | 27 | /** 模拟用户的输入 start **/ 28 | Parameter inputParam = new Parameter(); 29 | inputParam.setName("price"); 30 | inputParam.setCnName("价格"); 31 | inputParam.setType(TypeEnum.Double); 32 | inputParam.setValue("99"); 33 | /** 用户的输入 end **/ 34 | 35 | /** 需要满足的运算条件 start **/ 36 | Operation operation = new Operation(); 37 | operation.setCriticalType(CriticalConditionEnum.Operation); 38 | operation.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=100); 39 | operation.setPriority(1); 40 | operation.setExpectVal(String.valueOf(Double.parseDouble(inputParam.getValue())*0.9)); 41 | 42 | Operation operation2 = new Operation(); 43 | operation2.setCriticalType(CriticalConditionEnum.Operation); 44 | operation2.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=150); 45 | operation2.setPriority(2); 46 | operation2.setExpectVal(String.valueOf(Double.parseDouble(inputParam.getValue())*0.85)); 47 | 48 | Operation operation3 = new Operation(); 49 | operation3.setCriticalType(CriticalConditionEnum.Operation); 50 | operation3.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=200); 51 | operation3.setPriority(3); 52 | operation3.setExpectVal(String.valueOf(Double.parseDouble(inputParam.getValue())*0.8)); 53 | /** 需要满足的条件 end **/ 54 | 55 | Rule rule = new Rule(); 56 | rule.setInputParams(Arrays.asList(inputParam)); 57 | rule.setName("第八个规则例子"); 58 | rule.setCreateDate(new Date()); 59 | /** 需要根据前端输入的优先值,进行先后顺序绑定,高优先值,放在第一个 **/ 60 | rule.setOperation(operation3).exclude(operation2).exclude(operation); 61 | rule.setOutputType(TypeEnum.Double); 62 | /** 设置不满足条件返回值 **/ 63 | rule.setFalseValue(String.valueOf(Double.parseDouble(inputParam.getValue()))); 64 | /** 设置满足条件返回值 **/ 65 | //rule.setTrueValue(String.valueOf(Double.parseDouble(inputParam.getValue())*0.9)); 66 | 67 | Object strResult = engine.loadRule(rule).execute(); 68 | System.out.println("the result is "+strResult); 69 | System.out.println("the rule info is "+ rule); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/jp/nian/rule/engine/RuleTest9.java: -------------------------------------------------------------------------------- 1 | package com.jp.nian.rule.engine; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import com.jp.nian.rule.vo.CriticalConditionEnum; 6 | import com.jp.nian.rule.vo.Operation; 7 | import com.jp.nian.rule.vo.Parameter; 8 | import com.jp.nian.rule.vo.Rule; 9 | import com.jp.nian.rule.vo.TypeEnum; 10 | 11 | public class RuleTest9 { 12 | 13 | /** 14 | * main:有规则 15 | * 如果用户购买的商品满80,减5;满130减8;满170以上减10 16 | * 测试1:购买商品110元,期望输出110-5 17 | * 测试2:用户输入150元,期望输出150-8 18 | * 测试3:用户输入200元,期望输出200-10 19 | * 测试4:用户输入70元,期望输出70 20 | * @author tanfan 21 | * @param args 22 | * @since JDK 1.7 23 | */ 24 | public static void main(String[] args) throws Exception { 25 | RuleEngine engine = RuleEngineFactory.newInstance().getRuleEngine(); 26 | 27 | /** 模拟用户的输入 start **/ 28 | Parameter inputParam = new Parameter(); 29 | inputParam.setName("price"); 30 | inputParam.setCnName("价格"); 31 | inputParam.setType(TypeEnum.Double); 32 | inputParam.setValue("70"); 33 | /** 用户的输入 end **/ 34 | 35 | /** 需要满足的运算条件 start **/ 36 | Operation operation = new Operation(); 37 | /** 设置临界条件为运算**/ 38 | operation.setCriticalType(CriticalConditionEnum.Operation); 39 | /** 设置临界条件的运算**/ 40 | operation.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=80); 41 | operation.setPriority(1); 42 | operation.setExpectVal(String.valueOf(Double.parseDouble(inputParam.getValue())-5)); 43 | 44 | Operation operation2 = new Operation(); 45 | operation2.setCriticalType(CriticalConditionEnum.Operation); 46 | operation2.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=130); 47 | operation2.setPriority(2); 48 | operation2.setExpectVal(String.valueOf(Double.parseDouble(inputParam.getValue())-8)); 49 | 50 | Operation operation3 = new Operation(); 51 | operation3.setCriticalType(CriticalConditionEnum.Operation); 52 | operation3.setCriticalOperation(Double.parseDouble(inputParam.getValue())>=170); 53 | operation3.setPriority(3); 54 | operation3.setExpectVal(String.valueOf(Double.parseDouble(inputParam.getValue())-10)); 55 | /** 需要满足的条件 end **/ 56 | 57 | Rule rule = new Rule(); 58 | rule.setInputParams(Arrays.asList(inputParam)); 59 | rule.setName("第九个规则例子"); 60 | rule.setCreateDate(new Date()); 61 | /** 需要根据前端输入的优先值,进行先后顺序绑定,高优先值,放在第一个 **/ 62 | rule.setOperation(operation3).exclude(operation2).exclude(operation); 63 | rule.setOutputType(TypeEnum.Double); 64 | /** 设置不满足条件返回值 **/ 65 | rule.setFalseValue(String.valueOf(Double.parseDouble(inputParam.getValue()))); 66 | 67 | Object strResult = engine.loadRule(rule).execute(); 68 | System.out.println("the result is "+strResult); 69 | System.out.println("the rule info is "+ rule); 70 | } 71 | 72 | } 73 | --------------------------------------------------------------------------------