├── 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 | 
43 | 
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 |
--------------------------------------------------------------------------------