├── .gitignore
├── Drools-ComplexProblem.md
├── Drools-Example.md
├── Drools-Language.md
├── Drools-Use.md
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── xu
│ │ └── drools
│ │ ├── DroolsSpringbootApplication.java
│ │ ├── bean
│ │ ├── Golfer.java
│ │ ├── Hope.java
│ │ ├── Message.java
│ │ ├── Person.java
│ │ ├── Politician.java
│ │ ├── Rules.java
│ │ ├── Student.java
│ │ ├── World.java
│ │ └── XiaoMing.java
│ │ ├── common
│ │ ├── bean
│ │ │ └── ExceptionType.java
│ │ ├── exception
│ │ │ ├── BusinessException.java
│ │ │ └── JsonResponse.java
│ │ └── web
│ │ │ └── JsonHandlerExceptionResolver.java
│ │ ├── config
│ │ └── DataSourceConfig.java
│ │ ├── dao
│ │ └── RulesDao.java
│ │ ├── rule
│ │ ├── complexProblem
│ │ │ ├── GolferProblem.java
│ │ │ ├── MingDrink.java
│ │ │ └── WorldProblem.java
│ │ ├── honestpolitician
│ │ │ └── HonestPoliticianExample.java
│ │ ├── rule1
│ │ │ └── rule1.java
│ │ └── rule2
│ │ │ └── rule2.java
│ │ ├── service
│ │ ├── RuleTableService.java
│ │ └── RulesService.java
│ │ └── web
│ │ ├── ComplexProblem.java
│ │ └── RulesController.java
└── resources
│ ├── META-INF
│ └── kmodule.xml
│ ├── application.yml
│ ├── com
│ └── xu
│ │ └── drools
│ │ └── rule
│ │ ├── complexProblem
│ │ ├── golfer.drl
│ │ ├── ming.drl
│ │ └── world.drl
│ │ ├── honestpolitician
│ │ └── HonestPolitician.drl
│ │ ├── rule1
│ │ └── rule1.drl
│ │ └── rule2
│ │ └── rule2.drl
│ ├── drools_rule.sql
│ ├── log4j2.xml
│ └── tables
│ └── rule.xlsx
└── test
└── java
└── com
└── xu
└── drools
└── DroolsSpringbootApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 |
12 | ### IntelliJ IDEA ###
13 | .idea
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### NetBeans ###
19 | nbproject/private/
20 | build/
21 | nbbuild/
22 | dist/
23 | nbdist/
24 | .nb-gradle/
--------------------------------------------------------------------------------
/Drools-ComplexProblem.md:
--------------------------------------------------------------------------------
1 | ## Drools-Example
2 |
3 | 使用Drools来解决一些复杂的逻辑问题。
4 |
5 | ### MingDrink
6 |
7 | - problem
8 |
9 | 小明喝汽水问题:
10 |
11 | 1元钱一瓶汽水,喝完后两个空瓶换一瓶汽水,问:小明有20元钱,最多可以喝到几瓶汽水?
12 | - rule
13 |
14 | ```
15 | package com.xu.drools
16 |
17 | import com.xu.drools.bean.XiaoMing;
18 |
19 |
20 | // 小明喝汽水问题
21 | // 1元钱一瓶汽水,喝完后两个空瓶换一瓶汽水,问:小明有20元钱,最多可以喝到几瓶汽水?
22 | // 规则1:1元钱一瓶汽水
23 | // 规则2:两个空瓶换一瓶汽水
24 |
25 | //规则1:1元钱一瓶汽水。有钱就买水,空瓶+1,钱-1,喝水+1;
26 | rule "rule1"
27 | salience 3
28 | when
29 | $m:XiaoMing(money>0);
30 | then
31 | System.out.println("有钱即可喝水,钱:"+$m.getMoney());
32 | $m.setBottle($m.getBottle()+1);
33 | $m.setMoney($m.getMoney()-1);
34 | $m.setDrink($m.getDrink()+1);
35 | update($m)
36 | end
37 |
38 | //规则2:两个空瓶换一瓶汽水。有空瓶就换钱,空瓶-2,钱+1;
39 | rule "rule2"
40 | salience 2
41 | when
42 | $m:XiaoMing(bottle>=2);
43 | then
44 | System.out.println("有瓶子就换钱,瓶子:"+$m.getBottle());
45 | $m.setBottle($m.getBottle()-2);
46 | $m.setMoney($m.getMoney()+1);
47 | update($m)
48 | end
49 |
50 | //规则3,打印已经喝掉的数量
51 | rule "rule3"
52 | salience 1
53 | when
54 | $m:XiaoMing();
55 | then
56 | System.out.println("总共喝掉:"+$m.getDrink());
57 | end
58 | ```
59 |
60 | ### WorldProblem
61 |
62 | - problem
63 |
64 | 猜对错问题:
65 | 在一次数学竞赛中,获得前三名的同学是A,B,C. 老师对他们说:“祝贺你们,请你们猜一猜名次。”
66 | * 甲:“A是第二,C是第三.”
67 | * 乙:“A是第一,B是第三.”
68 | * 丙:“B是第二,A是第三.”
69 |
70 | `感觉有更好的方法,但是写不出规则来0.0`
71 | - rule
72 |
73 | ```
74 | package com.xu.drools
75 |
76 | import com.xu.drools.bean.Student;
77 | import com.xu.drools.bean.World
78 |
79 | rule "find jia1"
80 | salience 2
81 | when
82 | $jia1 : Student(name == "jia",word1=="A",word2=="C",desc1=="2",desc2!="3")
83 | then
84 | insert( new World($jia1.getDesc1(),0,$jia1.getDesc2()) );
85 | end
86 |
87 | rule "find jia2"
88 | salience 2
89 | when
90 | $jia2 : Student(name == "jia",word1=="A",word2=="C",desc1!="2",desc2=="3")
91 | then
92 | insert( new World($jia2.getDesc1(),0,$jia2.getDesc2()) );
93 | end
94 |
95 | rule "find yi1"
96 | salience 3
97 | when
98 | $yi1 : Student(name == "yi",word1=="A",word2=="B",desc1=="1",desc2!="3");
99 | $w : World(a==$yi1.getDesc1())
100 | then
101 | $w.setB($yi1.getDesc2());
102 | update($w)
103 | end
104 |
105 | rule "find yi2"
106 | salience 3
107 | when
108 | $yi2 : Student(name == "yi",word1=="A",word2=="B",desc1=="1",desc2!="3")
109 | $w : World(a==$yi2.getDesc1())
110 | then
111 | $w.setB($yi2.getDesc2());
112 | update($w)
113 | end
114 |
115 |
116 | rule "find bing1"
117 | salience 4
118 | when
119 | $bing1 : Student(name == "bing",word1=="A",word2=="B",desc1=="3",desc2!="2")
120 | $w : World(a==$bing1.getDesc1(),b==$bing1.getDesc2())
121 | then
122 | System.out.println("-------"+$w.toString());
123 | end
124 |
125 |
126 | rule "find bing2"
127 | salience 4
128 | when
129 | $bing2 : Student(name == "bing",word1=="A",word2=="B",desc1!="3",desc2=="2")
130 | $w : World(a==$bing2.getDesc1(),b==$bing2.getDesc2())
131 | then
132 | System.out.println("-------"+$w.toString());
133 | end
134 | ```
135 |
136 | ### GolferProblem
137 |
138 | - problem
139 |
140 | 高尔夫球员站位问题:
141 |
142 | 已知有四个高尔夫球员,他们的名字是Fred,Joe,Bob,Tom;
143 | * 今天他们分别穿着红色,蓝色,橙色,以及格子衣服,并且他们按照从左往右的顺序站成一排。
144 | * 我们将最左边的位置定为1,最右边的位置定为4,中间依次是2,3位置。
145 | * 现在我们了解的情况是:
146 | * 1.高尔夫球员Fred,目前不知道他的位置和衣服颜色
147 | * 2.Fred右边紧挨着的球员穿蓝色衣服
148 | * 3.Joe排在第2个位置
149 | * 4.Bob穿着格子短裤
150 | * 5.Tom没有排在第1位或第4位,也没有穿橙色衣服
151 | * 请问,这四名球员的位置和衣服颜色。
152 |
153 | - rule
154 |
155 | ```
156 | package com.xu.drools
157 |
158 | import com.xu.drools.bean.Golfer;
159 |
160 | rule "find solution"
161 | when
162 | //1.高尔夫球员Fred,目前不知道他的位置和衣服颜色
163 | $fred : Golfer( name == "Fred" )
164 |
165 | //3.Joe排在第2个位置
166 | $joe : Golfer( name == "Joe",
167 | position == 2,
168 | position != $fred.position,
169 | color != $fred.color )
170 |
171 | //4.Bob穿着格子短裤
172 | $bob : Golfer( name == "Bob",
173 | position != $fred.position,
174 | position != $joe.position,
175 | color == "plaid",
176 | color != $fred.color,
177 | color != $joe.color )
178 |
179 | //5.Tom没有排在第1位或第4位,也没有穿橙色衣服
180 | $tom : Golfer( name == "Tom",
181 | position != 1,
182 | position != 4,
183 | position != $fred.position,
184 | position != $joe.position,
185 | position != $bob.position,
186 | color != "orange",
187 | color != $fred.color,
188 | color != $joe.color,
189 | color != $bob.color )
190 |
191 | //2.Fred右边紧挨着的球员穿蓝色衣服
192 | Golfer( position == ( $fred.position + 1 ),
193 | color == "blue",
194 | this in ( $joe, $bob, $tom ) )
195 |
196 | then
197 | System.out.println( "Fred " + $fred.getPosition() + " " + $fred.getColor() );
198 | System.out.println( "Joe " + $joe.getPosition() + " " + $joe.getColor() );
199 | System.out.println( "Bob " + $bob.getPosition() + " " + $bob.getColor() );
200 | System.out.println( "Tom " + $tom.getPosition() + " " + $tom.getColor() );
201 | end
202 | ```
--------------------------------------------------------------------------------
/Drools-Example.md:
--------------------------------------------------------------------------------
1 | ## Drools-Example
2 |
3 | ### Honest Politician
4 |
5 | - 使用kmodule的方式调用drools
6 | 创建文件:/resources/META-INF/kmodule.xml
7 | ```
8 |
9 |
11 |
12 |
13 |
14 |
15 | ```
16 | - rule
17 | ```
18 | package com.xu.drools //package指定命名空间:com.xu.drools
19 |
20 | import com.xu.drools.bean.Politician; //import要使用的对象:Politician
21 | import com.xu.drools.bean.Hope; //import要使用的对象:Hope
22 |
23 | rule "We have an honest Politician" //rule,定义规则:We have an honest Politician
24 | salience 10 //salience,属性部分,定义优先级:10
25 | when
26 | exists( Politician( honest == true ) ) //exists,条件部分-LHS,定义当前规则的条件:存在honest==true的Politician
27 | then
28 | insertLogical( new Hope() ); //insertLogical,结果部分-RHS,定义规则满足后执行的操作:往当前workingMemory中插入一个新的Hope对象
29 | end //规则结束
30 |
31 | rule "Hope Lives"
32 | salience 10
33 | when
34 | exists( Hope() )
35 | then
36 | System.out.println("Hurrah!!! Democracy Lives");
37 | end
38 |
39 | rule "Hope is Dead"
40 | when
41 | not( Hope() ) //not,不存在:不存在Hope对象
42 | then
43 | System.out.println( "We are all Doomed!!! Democracy is Dead" );
44 | end
45 |
46 | rule "Corrupt the Honest"
47 | when
48 | politician : Politician( honest == true )
49 | exists( Hope() )
50 | then
51 | System.out.println( "I'm an evil corporation and I have corrupted " + politician.getName() );
52 | modify( politician ) { //modify,修改:修改politician的Honest为false
53 | setHonest( false )
54 | }
55 | end
56 | ```
57 | - 数据的输入
58 |
59 | ```
60 | public static void main(final String[] args) {
61 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
62 | System.out.println(kc.verify().getMessages().toString());
63 | execute( kc );
64 | }
65 |
66 | public static void execute( KieContainer kc ) {
67 | KieSession ksession = kc.newKieSession("HonestPoliticianKS");
68 |
69 | final Politician p1 = new Politician( "President of Umpa Lumpa", true );
70 | final Politician p2 = new Politician( "Prime Minster of Cheeseland", true );
71 | final Politician p3 = new Politician( "Tsar of Pringapopaloo", true );
72 | final Politician p4 = new Politician( "Omnipotence Om", true );
73 |
74 | ksession.insert( p1 );
75 | ksession.insert( p2 );
76 | ksession.insert( p3 );
77 | ksession.insert( p4 );
78 |
79 | ksession.fireAllRules();
80 |
81 | ksession.dispose();
82 | }
83 | ```
84 | - rule的执行顺序
85 |
86 | http://cdn.heroxu.com/20190829156706732481281.png
87 |
88 | 
89 |
90 | - 执行结果
91 | ```
92 | Hurrah!!! Democracy Lives
93 | I'm an evil corporation and I have corrupted President of Umpa Lumpa
94 | I'm an evil corporation and I have corrupted Prime Minster of Cheeseland
95 | I'm an evil corporation and I have corrupted Tsar of Pringapopaloo
96 | I'm an evil corporation and I have corrupted Omnipotence Om
97 | We are all Doomed!!! Democracy is Dead
98 | ```
99 |
--------------------------------------------------------------------------------
/Drools-Language.md:
--------------------------------------------------------------------------------
1 | [toc]
2 | ## Drools语法-Language
3 | ### 关键词
4 | - Hard keywords(Cannot use any):
5 |
6 | `true,false,null`
7 | - Soft keywords(avoid use)
8 |
9 | `lock-on-active date-effective date-expires no-loop auto-focus activation-group agenda-group ruleflow-group entry-point duration package import dialect salience enabled attributes rule extend when then template query declare function global eval not in or and exists forall accumulate collect from action reverse result end over init`
10 |
11 | ### 注释
12 | - 单行注释
13 |
14 | ```
15 | rule "Testing Comments"
16 | when
17 | // this is a single line comment
18 | eval( true ) // this is a comment in the same line of a pattern
19 | then
20 | // this is a comment inside a semantic code block
21 | end
22 | ```
23 | - 多行注释
24 |
25 | ```
26 | rule "Test Multi-line Comments"
27 | when
28 | /* this is a multi-line comment
29 | in the left hand side of a rule */
30 | eval( true )
31 | then
32 | /* and this is a multi-line comment
33 | in the right hand side of a rule */
34 | end
35 | ```
36 |
37 | ### Pakage
38 | - package
39 |
40 | `package`表示一个命名空间.package是必须定义的,必须放在规则文件第一行.
41 | - import
42 |
43 | `import`语句的工作方式类似于Java中的import语句。您需要为要在规则中使用的任何对象指定完全限定路径和类型名称。
44 | - global
45 |
46 | `global`用于定义全局变量。
47 |
48 | Rules:
49 | ```
50 | global java.util.List myGlobalList;
51 |
52 | rule "Using a global"
53 | when
54 | eval( true )
55 | then
56 | myGlobalList.add( "Hello World" );
57 | end
58 | ```
59 | Set the global value:
60 | ```
61 | List list = new ArrayList();
62 | KieSession kieSession = kiebase.newKieSession();
63 | kieSession.setGlobal( "myGlobalList", list );
64 | ```
65 |
66 | ### Function
67 | - function
68 |
69 | `function`是一种将语义代码放置在规则源文件中的方法,而不是普通的Java类
70 | ```
71 | function String hello(String name) {
72 | return "Hello "+name+"!";
73 | }
74 | import function my.package.Foo.hello
75 | rule "using a static function"
76 | when
77 | eval( true )
78 | then
79 | System.out.println( hello( "Bob" ) );
80 | end
81 | ```
82 |
83 | ### Query
84 | - query
85 |
86 | `query`是一种搜索工作内存中与指定条件匹配的事实的简单方法.
87 | ```
88 | 对所有30岁以上的人的简单查询
89 | query "people over the age of 30"
90 | person : Person( age > 30 )
91 | end
92 |
93 | 查询超过x岁的人,以及居住在y的人
94 | query "people over the age of x" (int x, String y)
95 | person : Person( age > x, location == y )
96 | end
97 |
98 | QueryResults results = ksession.getQueryResults( "people over the age of 30" );
99 | System.out.println( "we have " + results.size() + " people over the age of 30" );
100 |
101 | System.out.println( "These people are are over 30:" );
102 |
103 | for ( QueryResultsRow row : results ) {
104 | Person person = ( Person ) row.get( "person" );
105 | System.out.println( person.getName() + "\n" );
106 | }
107 | ```
108 |
109 | ### Rule
110 |
111 | `rule`定义规则。`rule "ruleName"`。
112 |
113 | 一个规则可以包含三个部分:属性部分,条件部分:即`LHS`,结果部分:即`RHS`.
114 | 
115 |
116 | #### 属性部分-Attributes
117 |
118 | 定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等。
119 | `activation-group` `agenda-group` `auto-focus` `date-effective` `date-expires` `dialect` `duration` `duration-value` `enabled` `lock-on-active` `no-loop` `ruleflow-group` `salience`
120 |
121 | 
122 |
123 | - no-loop
124 |
125 | 默认值:false
126 |
127 | 类型:Boolean
128 |
129 | 在一个规则当中如果条件满足就对`Working Memory`当中的某个Fact对象进行了修改,比如使用update 将其更新到当前的`Working Memory`当中,这时引擎会再次检查所有的规则是否满足条件,如果满足会再次执行.
130 | - ruleflow-group
131 |
132 | 默认值:N/A
133 |
134 | 类型:String
135 |
136 | `Ruleflow`是一个Drools功能,可让您控制规则的触发。由相同的规则流组标识汇编的规则仅在其组处于活动状态时触发。将规则划分为一个个的组,然后在规则流当中通过使用`ruleflow-group`属性的值,从而使用对应的规则。
137 | - lock-on-active
138 |
139 | 默认值:false
140 |
141 | 类型:Boolean
142 |
143 | 当在规则上使用`ruleflow-group` 属性或`agenda-group` 属性的时候,将`lock-on-action` 属性的值设置为true,可能避免因某些Fact 对象被修改而使已经执行过的规则再次被激活执行。可以看出该属性与`no-loop` 属性有相似之处,`no-loop` 属性是为了避免Fact 修改或调用了`insert`、`retract`、`update` 之类而导致规则再次激活执行,这里的`lock-on-action` 属性也是起这个作用,`lock-on-active` 是`no-loop` 的增强版属性,它主要作用在使用`ruleflow-group` 属性或`agenda-group` 属性的时候
144 |
145 | - salience
146 |
147 | 默认值:0
148 |
149 | 类型:integer
150 |
151 | 设置规则执行的优先级,`salience` 属性的值是一个数字,数字越大执行优先级越高,同时它的值可以是一个负数.
152 | 规则的`salience` 默认值为0,所以如果我们不手动设置规则的`salience` 属性,那么它的执行顺序是随机的.
153 |
154 | - agenda-group
155 |
156 | 默认值:MAIN
157 |
158 | 类型:String
159 |
160 | 规则的调用与执行是通过`StatelessSession` 或`StatefulSession` 来实现的,一般的顺序是创建一个`StatelessSession` 或`StatefulSession`,将各种经过编译的规则的package 添加到session当中,接下来将规则当中可能用到的Global对象和Fact对象插入到Session 当中,最后调用fireAllRules 方法来触发、执行规则。在没有调用最后一步`fireAllRules`方法之前,所有的规则及插入的`Fact`对象都存放在一个名叫`Agenda`表的对象当中,这个`Agenda`表中每一个规则及与其匹配相关业务数据叫做`Activation`,在调用`fireAllRules`方法后,这些Activation 会依次执行,这些位于Agenda 表中的Activation 的执行顺序在没有设置相关用来控制顺序的属性时(比如salience 属性),它的执行顺序是随机的,不确定的。`Agenda Group` 是用来在Agenda 的基础之上,对现在的规则进行再次分组,具体的分组方法可以采用为规则添加`agenda-group`属性来实现。`agenda-group` 属性的值也是一个字符串,通过这个字符串,可以将规则分为若干个`Agenda Group`,默认情况下,引擎在调用这些设置了`agenda-group` 属性的规则的时候需要显示的指定某个`Agenda Group` 得到`Focus`(焦点),这样位于该`Agenda Group` 当中的规则才会触发执行,否则将不执行。
161 |
162 | - auto-focus
163 |
164 | 默认值:false
165 |
166 | 类型:Boolean
167 |
168 | 用来在已设置了`agenda-group`的规则上设置该规则是否可以自动独取`Focus`,如果该属性设置为true,那么在引擎执行时,就不需要显示的为某个`Agenda Group`设置`Focus`,否则需要。对于规则的执行的控制,还可以使用`Agenda Filter` 来实现。在Drools 当中,提供了一个名为`org.drools.runtime.rule.AgendaFilter 的Agenda Filter` 接口,用户可以实现该接口,通过规则当中的某些属性来控制规则要不要执行。`org.drools.runtime.rule.AgendaFilter` 接口只有一个方法需要实现,方法体如下: ` public boolean accept(Activation activation);` 在该方法当中提供了一个`Activation` 参数,通过该参数我们可以得到当前正在执行的规则对象或其它一些属性,该方法要返回一个布尔值,该布尔值就决定了要不要执行当前这个规则,返回true 就执行规则,否则就不执行。
169 |
170 | - activation-group
171 |
172 | 默认值:N/A
173 |
174 | 类型:String
175 |
176 | 该属性的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,这样在执行的时候,具有相同`activation-group`属性的规则中只要有一个会被执行,其它的规则都将不再执行。也就是说,在一组具有相同`activation-group`属性的规则当中,只有一个规则会被执行,其它规则都将不会被执行。当然对于具有相同`activation-group`属性的规则当中究竟哪一个会先执行,则可以用类似`salience`之类属性来实现。
177 |
178 | - dialect
179 |
180 | 默认值: 根据package指定
181 |
182 | 类型:String,"java" or "mvel"
183 |
184 | `dialect`种类是用于LHS或RHS代码块中的任何代码表达式的语言。目前有两种`dialect`,`Java`和`MVEL`。虽然`dialect`可以在包级别指定,但此属性允许为规则覆盖包定义。
185 |
186 | - date-effective
187 |
188 | 默认值:N/A
189 |
190 | 类型:字符串,包含日期和时间定义。格式:`dd-MMM-yyyy`(25-Sep-2009).
191 |
192 | 仅当当前日期和时间在日期有效属性后面时,才能激活规则。
193 | - date-expires
194 |
195 | 默认值:N/A
196 |
197 | 类型:字符串,包含日期和时间定义。格式:`dd-MMM-yyyy`(25-Sep-2009).
198 |
199 | 如果当前日期和时间在`date-expires`属性之后,则无法激活规则.
200 | - enabled
201 |
202 | 默认值:false
203 |
204 | 类型:String
205 |
206 | 表示规则是可用的,如果手工为一个规则添加一个`enabled`属性,并且设置其`enabled`属性值为false,那么引擎就不会执行该规则.
207 |
208 | - duration
209 |
210 | 默认值:无
211 |
212 | 类型:long
213 |
214 | 持续时间指示规则将在指定的持续时间之后触发,如果它仍然是true.
215 |
216 | #### 条件部分-LHS
217 |
218 | 定义当前规则的条件,如`when Message()`; 判断当前workingMemory中是否存在Message对象。
219 |
220 | `Left Hand Side`(`LHS`)是规则的条件部分的公共名称。它由零个或多个条件元素组成。
221 | 如果LHS为空,它将被认为是一个条件元素,它总是为真,并且当创建一个新的WorkingMemory会话时,它将被激活一次。
222 | ```
223 | Conditions / LHS —匹配模式(Patterns)
224 |
225 | 没有字段约束的Pattern
226 | Person()
227 |
228 | 有文本字段约束的Pattern
229 | Person( name == “bob” )
230 |
231 | 字段绑定的Pattern
232 | Person( $name : name == “bob” )
233 | 变量名称可以是任何合法的java变量,$是可选的,可由于区分字段和变量
234 |
235 | Fact绑定的Pattern
236 | $bob : Person( name == “bob” )字段绑定的Pattern
237 |
238 | 变量约束的Pattern
239 | Person( name == $name )
240 | ```
241 |
242 | Drools提供了十二种类型比较操作符:
243 | `>` `>=` `<` `<=` `==` `!=` `contains` `not contains` `memberOf` `not memberOf` `matches` `not matches`
244 |
245 | - contains
246 |
247 | 运算符`contains`用于检查作为Collection或elements的字段是否包含指定的值.
248 | ```
249 | Cheese( name contains "tilto" )
250 | Person( fullName contains "Jr" )
251 | String( this contains "foo" )
252 | ```
253 | - not contains
254 |
255 | 和`contains`相反
256 |
257 | - memberOf
258 |
259 | 运算符`memberOf`用于检查字段是否是集合的成员或元素;该集合必须是一个变量。
260 | ```
261 | CheeseCounter( cheese memberOf $matureCheeses )
262 | ```
263 | - not memberOf
264 |
265 | 和`memberOf`相反
266 |
267 | - matches
268 |
269 | 正则表达式匹配,与java不同的是,不用考虑'/'的转义问题
270 | ```
271 | Cheese( type matches "(Buffalo)?\\S*Mozarella" )
272 | ```
273 | - not matches
274 |
275 | 和`matches`相反
276 |
277 | 其他条件元素:
278 | - exists
279 |
280 | 存在。检查Working Memory是否存在某物。使用模式`exists`,则规则将只激活最多一次,而不管在工作存储器中存在与存在模式中的条件匹配的数据量
281 |
282 | - not
283 |
284 | 不存在,检查工作存储器中是否存在某物。认为“`not`”意味着“`there must be none of...`”。
285 |
286 | #### 结果部分-RHS
287 |
288 | 这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用。
289 |
290 | `Right Hand Side`(`RHS`)是规则的结果或动作部分的通用名称;此部分应包含要执行的操作的列表。在规则的RHS中使用命令式或条件式代码是不好的做法;作为一个规则应该是`原子`的性质 - “`when this, then do this`”,而不是“`when this, maybe do this`”。规则的RHS部分也应该保持较小,从而保持声明性和可读性。如果你发现你需要在RHS中的命令式和/或条件代码,那么也许你应该把这个规则分成多个规则。 `RHS`的主要目的是插入,删除或修改工作存储器数据。为了协助,有一些方便的方法可以用来修改工作记忆;而不必首先引用工作内存实例。
291 |
292 | - update
293 |
294 | 更新,告诉引擎对象已经改变(已经绑定到LHS上的某个东西),并且规则可能需要重新考虑。
295 | - insert(new Something())
296 |
297 | 插入,往当前`workingMemory`中插入一个新的Fact对象,会触发规则的再次执行,除非使用`no-loop`限定;
298 |
299 | - insertLogical(new Something())
300 |
301 | 类似于`insert`,但是当没有更多的facts支持当前触发规则的真实性时,对象将被自动删除。
302 | - modify
303 |
304 | 修改,与`update`语法不同,结果都是更新操作。该语言扩展提供了一种结构化的方法来更新事实。它将更新操作与一些setter调用相结合来更改对象的字段。
305 | - retract
306 |
307 | 删除
308 |
309 | 一些内置的method。
310 |
311 | - drools.halt()
312 |
313 | 调用`drools.halt()`立即终止规则执行。这是需要将控制权返回到当前会话使用`fireUntilHalt()`的点。
314 | - drools.getWorkingMemory()
315 |
316 | 返回WorkingMemory对象.
317 | - drools.setFocus( String s)
318 |
319 | 将焦点设置为指定的`agenda group`.
320 | - drools.getRule().getName()
321 |
322 | 从规则的RHS调用,返回规则的名称。
323 | - drools.getTuple()
324 |
325 | 返回与当前执行的规则匹配的`Tuple`,而drools.getActivation()传递相应的激活。
326 |
--------------------------------------------------------------------------------
/Drools-Use.md:
--------------------------------------------------------------------------------
1 | ## Drools应用
2 |
3 | ### 动态规则
4 |
5 | #### 动态获取KieSession
6 | ```
7 | public KieSession getKieSession(String rules) {
8 | KieServices kieServices = KieServices.Factory.get();
9 | KieFileSystem kfs = kieServices.newKieFileSystem();
10 | kfs.write("src/main/resources/rules/rules.drl", rules.getBytes());
11 | KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
12 | Results results = kieBuilder.getResults();
13 | if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
14 | System.out.println(results.getMessages());
15 | throw new BusinessException(300003,results.getMessages().toString(),4);
16 | }
17 | KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
18 | KieBase kieBase = kieContainer.getKieBase();
19 |
20 | return kieBase.newKieSession();
21 | }
22 | ```
23 | #### 激活规则
24 | ```
25 | KieSession kieSession = rulesService.getKieSession(rule);
26 | Gson gson = new Gson();
27 | Person person = gson.fromJson(json, Person.class);
28 | kieSession.insert(person);
29 | kieSession.fireAllRules();
30 | kieSession.dispose();
31 | ```
32 |
33 | ### 决策表
34 |
35 | #### 将文件翻译为drl文件
36 | ```
37 | public String getRuleTable() {
38 | //把excel翻译成drl文件
39 | SpreadsheetCompiler compiler = new SpreadsheetCompiler();
40 | String rules = compiler.compile(ResourceFactory.newClassPathResource(RULES_PATH + File.separator + "rule.xlsx", "UTF-8"), "rule-table");
41 | System.out.println(rules);
42 | return rules;
43 | }
44 | ```
45 | #### 将文件流翻译为drl文件
46 | ```
47 | public String getRuleTable(InputStream inputStream) {
48 | //把excel翻译成drl文件
49 | SpreadsheetCompiler compiler = new SpreadsheetCompiler();
50 | String rules = compiler.compile(ResourceFactory.newInputStreamResource(inputStream, "UTF-8"), "rule-table");
51 | logger.info("get rule from xls:" + rules);
52 | return rules;
53 | }
54 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # drools-spring-boot
2 |
3 | 规则引擎Drools与SpringBoot的使用
4 |
5 | ## SpringBoot与Drools
6 |
7 | #### SpringBoot项目
8 | 略
9 | #### Drools
10 | - 依赖
11 | ```
12 | 6.5.0.Final
13 |
14 |
15 | org.kie
16 | kie-api
17 | ${drools.version}
18 |
19 |
20 | org.drools
21 | drools-core
22 | ${drools.version}
23 |
24 |
25 | org.drools
26 | drools-compiler
27 | ${drools.version}
28 |
29 |
30 | org.drools
31 | drools-decisiontables
32 | ${drools.version}
33 |
34 |
35 | org.drools
36 | drools-templates
37 | ${drools.version}
38 |
39 | ```
40 |
41 |
42 | ## Drools
43 |
44 | - 规则
45 | [Drools-Language](https://github.com/MyHerux/drools-springboot/blob/master/Drools-Language.md)
46 |
47 | - Rule示例
48 | [Drools-Example](https://github.com/MyHerux/drools-springboot/blob/master/Drools-Example.md)
49 |
50 | - Drools动态规则与决策表
51 | [Drools-Use](https://github.com/MyHerux/drools-springboot/blob/master/Drools-Use.md)
52 |
53 | - Drools解决复杂逻辑问题
54 | [Drools-ComplexProblem](https://github.com/MyHerux/drools-springboot/blob/master/Drools-ComplexProblem.md)
55 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.xu
7 | drools-springboot
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | drools-springboot
12 | Demo project for Spring Boot
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 1.4.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 | com.xu.drools.DroolsSpringbootApplication
27 |
28 | 6.5.0.Final
29 | 1.0.18
30 | 3.4.1
31 | 1.1.1
32 |
33 |
34 |
35 |
36 |
37 | org.kie
38 | kie-api
39 | ${drools.version}
40 |
41 |
42 | org.drools
43 | drools-core
44 | ${drools.version}
45 |
46 |
47 | org.drools
48 | drools-compiler
49 | ${drools.version}
50 |
51 |
52 | org.drools
53 | drools-decisiontables
54 | ${drools.version}
55 |
56 |
57 | org.drools
58 | drools-templates
59 | ${drools.version}
60 |
61 |
62 |
63 |
64 | org.springframework.boot
65 | spring-boot-starter
66 |
67 |
68 | org.springframework.boot
69 | spring-boot-starter-logging
70 |
71 |
72 |
73 |
74 |
75 |
76 | org.springframework.boot
77 | spring-boot-starter-log4j2
78 |
79 |
80 |
81 | org.springframework.boot
82 | spring-boot-starter-aop
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-starter-web
87 |
88 |
89 | org.springframework.boot
90 | spring-boot-starter-tomcat
91 |
92 |
93 | org.apache.tomcat.embed
94 | tomcat-embed-jasper
95 |
96 |
97 |
98 |
99 | mysql
100 | mysql-connector-java
101 |
102 |
103 | org.apache.tomcat
104 | tomcat-jdbc
105 |
106 |
107 | com.alibaba
108 | druid
109 | ${druid.version}
110 |
111 |
112 | org.mybatis
113 | mybatis
114 | ${mybatis.version}
115 |
116 |
117 |
118 | org.mybatis.spring.boot
119 | mybatis-spring-boot-starter
120 | ${mybatis-spring-boot.version}
121 |
122 |
123 |
124 |
125 | com.hynnet
126 | json-lib
127 | 2.4
128 |
129 |
130 | com.google.code.gson
131 | gson
132 |
133 |
134 |
135 |
136 | io.springfox
137 | springfox-swagger2
138 | 2.5.0
139 |
140 |
141 | io.springfox
142 | springfox-swagger-ui
143 | 2.5.0
144 |
145 |
146 |
147 | org.springframework.boot
148 | spring-boot-starter-test
149 | test
150 |
151 |
152 | org.springframework
153 | spring-jdbc
154 | 5.0.0.BUILD-SNAPSHOT
155 |
156 |
157 |
158 |
159 |
160 | spring-snapshots
161 | http://repo.spring.io/libs-snapshot
162 |
163 |
164 |
165 |
166 |
167 | spring-snapshots
168 | http://repo.spring.io/libs-snapshot
169 |
170 |
171 |
172 |
173 |
174 | fullProfile
175 |
176 |
177 | full
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | org.springframework.boot
187 | spring-boot-maven-plugin
188 |
189 | ${start-class}
190 |
191 |
192 |
193 |
194 | repackage
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/DroolsSpringbootApplication.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.annotation.ComponentScan;
6 | import org.springframework.scheduling.annotation.EnableScheduling;
7 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
8 |
9 | @SpringBootApplication
10 | @ComponentScan(basePackages ="com.xu.drools")
11 | @EnableScheduling
12 | @EnableSwagger2
13 | public class DroolsSpringbootApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(DroolsSpringbootApplication.class, args);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Golfer.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | public class Golfer{
4 |
5 | private String name;
6 | private String color;
7 | private int position;
8 |
9 | public Golfer(String name, String color, int position) {
10 | this.name = name;
11 | this.color = color;
12 | this.position = position;
13 | }
14 |
15 | public String getName() {
16 | return name;
17 | }
18 |
19 | public void setName(String name) {
20 | this.name = name;
21 | }
22 |
23 | public String getColor() {
24 | return color;
25 | }
26 |
27 | public void setColor(String color) {
28 | this.color = color;
29 | }
30 |
31 | public int getPosition() {
32 | return position;
33 | }
34 |
35 | public void setPosition(int position) {
36 | this.position = position;
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Hope.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | public class Hope {
4 |
5 | public Hope() {
6 |
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Message.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | import java.io.Serializable;
4 |
5 | public class Message implements Serializable{
6 |
7 | private static final long serialVersionUID = 1L;
8 |
9 | private String status;
10 |
11 | public String getStatus() {
12 | return status;
13 | }
14 |
15 | public void setStatus(String status) {
16 | this.status = status;
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Person.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 |
4 | import java.io.Serializable;
5 |
6 | public class Person implements Serializable {
7 |
8 | private static final long serialVersionUID = 1L;
9 |
10 | private Integer age;
11 |
12 | private String name;
13 |
14 | private String desc;
15 |
16 |
17 |
18 | public Person() {
19 | }
20 |
21 | public Person(Integer age, String name, String desc) {
22 | this.age = age;
23 | this.name = name;
24 | this.desc = desc;
25 | }
26 |
27 | public Integer getAge() {
28 | return age;
29 | }
30 |
31 | public void setAge(Integer age) {
32 | this.age = age;
33 | }
34 |
35 | public String getName() {
36 | return name;
37 | }
38 |
39 | public void setName(String name) {
40 | this.name = name;
41 | }
42 |
43 | public String getDesc() {
44 | return desc;
45 | }
46 |
47 | public void setDesc(String desc) {
48 | this.desc = desc;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Politician.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | public class Politician {
4 | private String name;
5 |
6 | private boolean honest;
7 |
8 | public Politician() {
9 |
10 | }
11 |
12 | public Politician(String name,
13 | boolean honest) {
14 | super();
15 | this.name = name;
16 | this.honest = honest;
17 | }
18 |
19 | public boolean isHonest() {
20 | return honest;
21 | }
22 |
23 | public void setHonest(boolean honest) {
24 | this.honest = honest;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Rules.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 |
4 | import java.util.Date;
5 |
6 | public class Rules {
7 |
8 | private Integer id;
9 | private String rule;
10 | private String name;
11 | private Date create_time;
12 | private Date update_time;
13 | private Integer visible;
14 |
15 | public String getRule() {
16 | return rule;
17 | }
18 |
19 | public void setRule(String rule) {
20 | this.rule = rule;
21 | }
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public void setName(String name) {
27 | this.name = name;
28 | }
29 |
30 | public Integer getId() {
31 | return id;
32 | }
33 |
34 | public void setId(Integer id) {
35 | this.id = id;
36 | }
37 |
38 | public Integer getVisible() {
39 | return visible;
40 | }
41 |
42 | public void setVisible(Integer visible) {
43 | this.visible = visible;
44 | }
45 |
46 | public Date getUpdate_time() {
47 | return update_time;
48 | }
49 |
50 | public void setUpdate_time(Date update_time) {
51 | this.update_time = update_time;
52 | }
53 |
54 | public Date getCreate_time() {
55 | return create_time;
56 | }
57 |
58 | public void setCreate_time(Date create_time) {
59 | this.create_time = create_time;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/Student.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | /**
4 | * Created by xu on 2017/6/5.
5 | */
6 | public class Student {
7 | private String name;
8 | private String word1;
9 | private String word2;
10 | private Integer desc1;
11 | private Integer desc2;
12 |
13 | public Student(String name, String word1, String word2, Integer desc1, Integer desc2) {
14 | this.name = name;
15 | this.word1 = word1;
16 | this.word2 = word2;
17 | this.desc1 = desc1;
18 | this.desc2 = desc2;
19 | }
20 |
21 | public String getName() {
22 | return name;
23 | }
24 |
25 | public void setName(String name) {
26 | this.name = name;
27 | }
28 |
29 | public String getWord1() {
30 | return word1;
31 | }
32 |
33 | public void setWord1(String word1) {
34 | this.word1 = word1;
35 | }
36 |
37 | public String getWord2() {
38 | return word2;
39 | }
40 |
41 | public void setWord2(String word2) {
42 | this.word2 = word2;
43 | }
44 |
45 | public Integer getDesc1() {
46 | return desc1;
47 | }
48 |
49 | public void setDesc1(Integer desc1) {
50 | this.desc1 = desc1;
51 | }
52 |
53 | public Integer getDesc2() {
54 | return desc2;
55 | }
56 |
57 | public void setDesc2(Integer desc2) {
58 | this.desc2 = desc2;
59 | }
60 |
61 |
62 | @Override
63 | public String toString() {
64 | return "Student{" +
65 | "name='" + name + '\'' +
66 | ", word1='" + word1 + '\'' +
67 | ", word2='" + word2 + '\'' +
68 | ", desc1=" + desc1 +
69 | ", desc2=" + desc2 +
70 | '}';
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/World.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | /**
4 | * Created by xu on 2017/6/6.
5 | */
6 | public class World {
7 | private Integer a;
8 | private Integer b;
9 | private Integer c;
10 |
11 | public World(Integer a, Integer b, Integer c) {
12 | this.a = a;
13 | this.b = b;
14 | this.c = c;
15 | }
16 |
17 | public Integer getA() {
18 | return a;
19 | }
20 |
21 | public void setA(Integer a) {
22 | this.a = a;
23 | }
24 |
25 | public Integer getB() {
26 | return b;
27 | }
28 |
29 | public void setB(Integer b) {
30 | this.b = b;
31 | }
32 |
33 | public Integer getC() {
34 | return c;
35 | }
36 |
37 | public void setC(Integer c) {
38 | this.c = c;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return "World{" +
44 | "a=" + a +
45 | ", b=" + b +
46 | ", c=" + c +
47 | '}';
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/bean/XiaoMing.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.bean;
2 |
3 | /**
4 | * Created by xu on 2017/6/5.
5 | * 小明喝水问题中的小明
6 | */
7 | public class XiaoMing {
8 |
9 | //总共的钱
10 | private int money;
11 | //空瓶子数目
12 | private int bottle;
13 | //已经喝掉的汽水
14 | private int drink;
15 |
16 | public int getMoney() {
17 | return money;
18 | }
19 |
20 | public void setMoney(int money) {
21 | this.money = money;
22 | }
23 |
24 | public int getBottle() {
25 | return bottle;
26 | }
27 |
28 | public void setBottle(int bottle) {
29 | this.bottle = bottle;
30 | }
31 |
32 | public int getDrink() {
33 | return drink;
34 | }
35 |
36 | public void setDrink(int drink) {
37 | this.drink = drink;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/common/bean/ExceptionType.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.common.bean;
2 |
3 | /**
4 | * Enum 响应类型
5 | *
6 | * @date 16/08/01
7 | * @auther hua xu
8 | */
9 | public enum ExceptionType {
10 | SUCCESS(200, "success",2),
11 | SYSTEM_ERROR(300001, "系统错误", 5),
12 | RULE_IS_NULL(300002, "系统错误", 2),
13 | RULE_IS_ERROR(300003, "规则语句错误", 2);
14 |
15 | private int code;
16 | private String message;
17 | private int level;
18 |
19 | ExceptionType(int code, String message, int level) {
20 | this.code = code;
21 | this.message = message;
22 | this.level = level;
23 | }
24 |
25 | public int getCode() {
26 | return code;
27 | }
28 |
29 | public String getMessage() {
30 | return message;
31 | }
32 |
33 | public int getLevel() {
34 | return level;
35 | }
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/common/exception/BusinessException.java:
--------------------------------------------------------------------------------
1 |
2 | package com.xu.drools.common.exception;
3 |
4 |
5 | import com.xu.drools.common.bean.ExceptionType;
6 |
7 | /**
8 | * 业务异常
9 | *
10 | * @author xuhua
11 | * @since 1.0.0
12 | */
13 | public class BusinessException extends RuntimeException {
14 |
15 | private int code;
16 |
17 | private String message;
18 |
19 | private int level;
20 |
21 | public BusinessException(ExceptionType exceptionType) {
22 | this.code = exceptionType.getCode();
23 | this.message = exceptionType.getMessage();
24 | this.level = exceptionType.getLevel();
25 | }
26 |
27 | public BusinessException(int code, String message, int level) {
28 | this.code = code;
29 | this.message = message;
30 | this.level = level;
31 | }
32 |
33 | public int getCode() {
34 | return code;
35 | }
36 |
37 | @Override
38 | public String getMessage() {
39 | return message;
40 | }
41 |
42 | public int getLevel() {
43 | return level;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/common/exception/JsonResponse.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.common.exception;
2 |
3 |
4 |
5 | /**
6 | * 业务异常类json
7 | *
8 | * @author xuhua
9 | * @since 1.0.0
10 | */
11 | public class JsonResponse {
12 | private int code;
13 | private int level;
14 | private String message;
15 | private Object data;
16 |
17 | public JsonResponse(Exception exception) {
18 | if (exception instanceof BusinessException) {
19 | BusinessException businessException = (BusinessException) exception;
20 | this.code = businessException.getCode();
21 | this.message = businessException.getMessage();
22 | this.level = businessException.getLevel();
23 | } else {
24 | this.code = 500;
25 | this.message = "传入数据错误";
26 | this.level = 5;
27 | }
28 | }
29 |
30 | public JsonResponse(Object data) {
31 | this.code = 200;
32 | this.message = "success";
33 | this.data = data;
34 | }
35 |
36 | public int getCode() {
37 | return code;
38 | }
39 |
40 | public void setCode(int code) {
41 | this.code = code;
42 | }
43 |
44 | public String getMessage() {
45 | return message;
46 | }
47 |
48 | public void setMessage(String message) {
49 | this.message = message;
50 | }
51 |
52 | public Object getData() {
53 | return data;
54 | }
55 |
56 | public void setData(Object data) {
57 | this.data = data;
58 | }
59 |
60 | public int getLevel() {
61 | return level;
62 | }
63 |
64 | public void setLevel(int level) {
65 | this.level = level;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/common/web/JsonHandlerExceptionResolver.java:
--------------------------------------------------------------------------------
1 |
2 | package com.xu.drools.common.web;
3 |
4 |
5 | import com.xu.drools.common.exception.BusinessException;
6 | import com.xu.drools.common.exception.JsonResponse;
7 | import net.sf.json.JSONObject;
8 | import org.apache.logging.log4j.LogManager;
9 | import org.apache.logging.log4j.Logger;
10 | import org.springframework.stereotype.Component;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.method.HandlerMethod;
14 | import org.springframework.web.servlet.HandlerExceptionResolver;
15 | import org.springframework.web.servlet.ModelAndView;
16 |
17 | import javax.servlet.http.HttpServletRequest;
18 | import javax.servlet.http.HttpServletResponse;
19 | import java.io.IOException;
20 | import java.util.Map;
21 |
22 | @Component
23 | public class JsonHandlerExceptionResolver implements HandlerExceptionResolver {
24 |
25 | private static Logger logger = LogManager.getLogger();
26 |
27 | @ResponseBody
28 | @Override
29 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
30 | Object handler, Exception exception) {
31 | ModelAndView mv = new ModelAndView();
32 | Map parameterMap = request.getParameterMap();
33 | logException(handler, request, exception, parameterMap);
34 | JsonResponse jsonResponse = new JsonResponse(exception);
35 | JSONObject result = new JSONObject();
36 | result.put("code", jsonResponse.getCode());
37 | result.put("message", jsonResponse.getMessage());
38 | try {
39 | response.setHeader("Content-type", "application/json;charset=UTF-8");
40 | response.getWriter().write(result.toString());
41 | } catch (IOException e) {
42 | logger.error("json response error", exception);
43 | logger.error("error", e);
44 | }
45 | return mv;
46 | }
47 |
48 | private void logException(Object handler, HttpServletRequest request,
49 | Exception exception, Map parameterMap) {
50 | if (handler != null && HandlerMethod.class.isAssignableFrom(handler.getClass())) {
51 | try {
52 | HandlerMethod handlerMethod = (HandlerMethod) handler;
53 | Class> beanType = handlerMethod.getBeanType();
54 | String methodName = handlerMethod.getMethod().getName();
55 | RequestMapping controllerRequestMapping = beanType.getDeclaredAnnotation(RequestMapping.class);
56 | String classMapping = "";
57 | if (controllerRequestMapping != null) {
58 | classMapping = controllerRequestMapping.value()[0];
59 | }
60 | RequestMapping methodRequestMapping = handlerMethod.getMethodAnnotation(RequestMapping.class);
61 | String methodMapping = "";
62 | if (methodRequestMapping != null) {
63 | methodMapping = methodRequestMapping.value()[0];
64 | }
65 | if (!methodMapping.startsWith("/")) {
66 | methodMapping = "/" + methodMapping;
67 | }
68 | String userInfo;
69 | try {
70 | userInfo = request.getSession().getAttribute("AccountName").toString();
71 | } catch (Exception e) {
72 | userInfo = "无授权回调";
73 | }
74 | Logger logger = LogManager.getLogger(beanType);
75 | if (exception instanceof BusinessException) {
76 | int level = ((BusinessException) exception).getLevel();
77 | if (level > 4) {
78 | logger.error("User is:" + userInfo +
79 | "RequestMapping is:" + classMapping + methodMapping +
80 | " HandlerMethod is:" + beanType.getSimpleName() + "." + methodName + "()"
81 | + " ParameterMap is:" + JSONObject.fromObject(parameterMap).toString());
82 | logger.error(msg(exception));
83 | } else {
84 | logger.info("level:" + level);
85 | logger.info("RequestMapping is:" + classMapping + methodMapping);
86 | logger.info("HandlerMethod is:" + beanType.getSimpleName() + "." + methodName + "()");
87 | logger.info("ParameterMap is:" + JSONObject.fromObject(parameterMap).toString());
88 | logger.info("exception is:" + exception.getMessage());
89 | }
90 | } else {
91 | logger.error("User is:" + userInfo
92 | + " RequestMapping is:" + classMapping + methodMapping
93 | + " HandlerMethod is:" + beanType.getSimpleName() + "." + methodName + "()"
94 | + " ParameterMap is:" + JSONObject.fromObject(parameterMap).toString()
95 | + " Exception is:" + exception.toString());
96 | logger.error(msg(exception));
97 | }
98 | } catch (Exception e) {
99 | e.printStackTrace();
100 | logger.error(handler + " execute failed.", exception);
101 | logger.error("error", e);
102 | }
103 | } else {
104 | logger.error(handler + " execute failed.", exception);
105 | }
106 | }
107 |
108 | private String msg(Exception e) {
109 | StringBuilder builder = new StringBuilder();
110 | StackTraceElement[] elements = e.getStackTrace();
111 | builder.append(e.getClass());
112 | builder.append(":");
113 | builder.append(e.getMessage());
114 | builder.append("\n");
115 |
116 | for (StackTraceElement element : elements) {
117 | String className = element.getClassName();
118 | if (className != null) {
119 | builder.append("\t");
120 | builder.append(element.getClassName());
121 | builder.append("#");
122 | builder.append(element.getMethodName());
123 | builder.append("(");
124 | builder.append(element.getFileName());
125 | builder.append(":");
126 | builder.append(element.getLineNumber());
127 | builder.append(")\n");
128 | }
129 | }
130 |
131 | return builder.toString();
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/config/DataSourceConfig.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.config;
2 |
3 | import org.apache.ibatis.session.SqlSessionFactory;
4 | import org.mybatis.spring.SqlSessionFactoryBean;
5 | import org.mybatis.spring.annotation.MapperScan;
6 | import org.springframework.beans.factory.annotation.Qualifier;
7 | import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
8 | import org.springframework.boot.context.properties.ConfigurationProperties;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.context.annotation.Primary;
12 | import org.springframework.jdbc.datasource.DataSourceTransactionManager;
13 |
14 | import javax.sql.DataSource;
15 |
16 | @Configuration
17 | @MapperScan(basePackages = DataSourceConfig.PACKAGE, sqlSessionFactoryRef = "SqlSessionFactory")
18 | public class DataSourceConfig {
19 | static final String PACKAGE = "com.xu.drools.dao";
20 |
21 |
22 | @Primary
23 | @Bean(name = "DataSource")
24 | @ConfigurationProperties(prefix="spring.datasource")
25 | public DataSource DataSource() {
26 | return DataSourceBuilder.create().build();
27 | }
28 |
29 | @Bean(name = "TransactionManager")
30 | @Primary
31 | public DataSourceTransactionManager dbTransactionManager() {
32 | return new DataSourceTransactionManager(DataSource());
33 | }
34 |
35 | @Bean(name = "SqlSessionFactory")
36 | @Primary
37 | public SqlSessionFactory dbSqlSessionFactory(@Qualifier("DataSource") DataSource DataSource) throws Exception {
38 | final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
39 | sessionFactory.setDataSource(DataSource);
40 | return sessionFactory.getObject();
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/dao/RulesDao.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.dao;
2 |
3 |
4 | import com.xu.drools.bean.Rules;
5 | import org.apache.ibatis.annotations.*;
6 |
7 | import java.util.List;
8 |
9 | @Mapper
10 | public interface RulesDao {
11 |
12 | @Select("SELECT * FROM drools_rule where id = #{id}")
13 | Rules getById(@Param("id") Integer id);
14 |
15 | @Insert("INSERT INTO drools_rule(name,rule) VALUE(#{name},#{rule})")
16 | Integer setRule(@Param("name") String name,@Param("rule") String rule);
17 |
18 | @Select("SELECT * FROM drools_rule order by create_time DESC")
19 | List getRuleList();
20 |
21 | @Update("UPDATE drools_rule SET visible=0 WHERE id = #{id}")
22 | Integer deleteRule(@Param("id") Integer id);
23 |
24 | @Update("UPDATE drools_rule SET rule= #{rule} AND name = #{name} WHERE id = #{id}")
25 | Integer updateRule(@Param("id") Integer id,@Param("name") String name,@Param("rule") String rule);
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/rule/complexProblem/GolferProblem.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.rule.complexProblem;
2 |
3 | import com.xu.drools.bean.Golfer;
4 | import org.kie.api.KieServices;
5 | import org.kie.api.runtime.KieContainer;
6 | import org.kie.api.runtime.KieSession;
7 |
8 | /**
9 | * 使用kmodule的方式调用drools
10 | * /resources/META-INF/kmodule.xml
11 | * 高尔夫球员站位问题
12 | */
13 | public class GolferProblem {
14 |
15 | /**
16 | * 已知有四个高尔夫球员,他们的名字是Fred,Joe,Bob,Tom;
17 | * 今天他们分别穿着红色,蓝色,橙色,以及格子衣服,并且他们按照从左往右的顺序站成一排。
18 | * 我们将最左边的位置定为1,最右边的位置定为4,中间依次是2,3位置。
19 | * 现在我们了解的情况是:
20 | * 1.高尔夫球员Fred,目前不知道他的位置和衣服颜色
21 | * 2.Fred右边紧挨着的球员穿蓝色衣服
22 | * 3.Joe排在第2个位置
23 | * 4.Bob穿着格子短裤
24 | * 5.Tom没有排在第1位或第4位,也没有穿橙色衣服
25 | * 请问,这四名球员的位置和衣服颜色。
26 | */
27 | public static void main(final String[] args) {
28 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
29 | System.out.println(kc.verify().getMessages().toString());
30 | execute(kc);
31 | }
32 |
33 | private static void execute(KieContainer kc) {
34 | KieSession ksession = kc.newKieSession("mingKS");
35 | String[] names = new String[]{"Fred", "Joe", "Bob", "Tom"};
36 | String[] colors = new String[]{"red", "blue", "plaid", "orange"};
37 | int[] positions = new int[]{1, 2, 3, 4};
38 |
39 | for (String name : names) {
40 | for (String color : colors) {
41 | for (int position : positions) {
42 | ksession.insert(new Golfer(name, color, position));
43 | }
44 | }
45 | }
46 | ksession.fireAllRules();
47 | ksession.dispose();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/rule/complexProblem/MingDrink.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.rule.complexProblem;
2 |
3 | import com.xu.drools.bean.XiaoMing;
4 | import org.kie.api.KieServices;
5 | import org.kie.api.runtime.KieContainer;
6 | import org.kie.api.runtime.KieSession;
7 |
8 | /**
9 | * 使用kmodule的方式调用drools
10 | * /resources/META-INF/kmodule.xml
11 | * 小明喝水问题
12 | */
13 | public class MingDrink {
14 |
15 | /**
16 | * 小明喝汽水问题
17 | *
18 | * 1元钱一瓶汽水,喝完后两个空瓶换一瓶汽水,问:小明有20元钱,最多可以喝到几瓶汽水?
19 | */
20 | public static void main(final String[] args) {
21 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
22 | System.out.println(kc.verify().getMessages().toString());
23 | execute(kc);
24 | }
25 |
26 | private static void execute(KieContainer kc) {
27 | KieSession ksession = kc.newKieSession("mingKS");
28 | XiaoMing xiaoMing=new XiaoMing();
29 | xiaoMing.setMoney(50);
30 | ksession.insert(xiaoMing);
31 | ksession.fireAllRules();
32 | ksession.dispose();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/rule/complexProblem/WorldProblem.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.rule.complexProblem;
2 |
3 | import com.xu.drools.bean.Student;
4 | import org.kie.api.KieServices;
5 | import org.kie.api.runtime.KieContainer;
6 | import org.kie.api.runtime.KieSession;
7 |
8 | /**
9 | * 使用kmodule的方式调用drools
10 | * /resources/META-INF/kmodule.xml
11 | * 猜对错问题
12 | */
13 | public class WorldProblem {
14 |
15 | /**
16 | * 在一次数学竞赛中,获得前三名的同学是A,B,C. 老师对他们说:“祝贺你们,请你们猜一猜名次。”
17 | * 甲:“A是第二,C是第三.”
18 | * 乙:“A是第一,B是第三.”
19 | * 丙:“B是第二,A是第三.”
20 | * 感觉有更好的方法,但是写不出规则来0.0
21 | */
22 | public static void main(final String[] args) {
23 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
24 | System.out.println(kc.verify().getMessages().toString());
25 | execute(kc);
26 | }
27 |
28 | private static void execute(KieContainer kc) {
29 | KieSession ksession = kc.newKieSession("worldKS");
30 | String[] names = new String[]{"jia", "yi", "bing"};
31 | String[] word1 = new String[]{"A", "B", "C"};
32 | String[] word2 = new String[]{"A", "B", "C"};
33 | int[] desc1 = new int[]{1, 2, 3};
34 | int[] desc2 = new int[]{1, 2, 3};
35 | for (String n : names) {
36 | for (String w1 : word1) {
37 | for (String w2 : word2) {
38 | for (int d1 : desc1) {
39 | for (int d2 : desc2) {
40 | Student student = new Student(n, w1, w2, d1, d2);
41 | ksession.insert(student);
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
48 | ksession.fireAllRules();
49 | ksession.dispose();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/rule/honestpolitician/HonestPoliticianExample.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.rule.honestpolitician;
2 |
3 | import com.xu.drools.bean.Politician;
4 | import org.kie.api.KieServices;
5 | import org.kie.api.runtime.KieContainer;
6 | import org.kie.api.runtime.KieSession;
7 |
8 | /**
9 | * 使用kmodule的方式调用drools
10 | * /resources/META-INF/kmodule.xml
11 | */
12 | public class HonestPoliticianExample {
13 |
14 | public static void main(final String[] args) {
15 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
16 | System.out.println(kc.verify().getMessages().toString());
17 | execute(kc);
18 | }
19 |
20 | private static void execute(KieContainer kc) {
21 | KieSession ksession = kc.newKieSession("HonestPoliticianKS");
22 |
23 | final Politician p1 = new Politician("President of Umpa Lumpa", true);
24 | final Politician p2 = new Politician("Prime Minster of Cheeseland", true);
25 | final Politician p3 = new Politician("Tsar of Pringapopaloo", true);
26 | final Politician p4 = new Politician("Omnipotence Om", true);
27 |
28 | ksession.insert(p1);
29 | ksession.insert(p2);
30 | ksession.insert(p3);
31 | ksession.insert(p4);
32 |
33 | ksession.fireAllRules();
34 |
35 | ksession.dispose();
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/rule/rule1/rule1.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.rule.rule1;
2 |
3 | import org.kie.api.KieServices;
4 | import org.kie.api.runtime.KieContainer;
5 | import org.kie.api.runtime.KieSession;
6 |
7 | /**
8 | * 使用kmodule的方式调用drools
9 | * /resources/META-INF/kmodule.xml
10 | */
11 | public class rule1 {
12 | public static void main(final String[] args) {
13 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
14 | System.out.println(kc.verify().getMessages().toString());
15 | execute(kc);
16 | }
17 |
18 | private static void execute(KieContainer kc) {
19 | KieSession ksession = kc.newKieSession("rule1KS");
20 |
21 |
22 | ksession.fireAllRules();
23 |
24 | ksession.dispose();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/rule/rule2/rule2.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.rule.rule2;
2 |
3 | import com.xu.drools.bean.Person;
4 | import org.kie.api.KieServices;
5 | import org.kie.api.runtime.KieContainer;
6 | import org.kie.api.runtime.KieSession;
7 | import org.kie.api.runtime.rule.QueryResults;
8 | import org.kie.api.runtime.rule.QueryResultsRow;
9 |
10 | /**
11 | * 使用kmodule的方式调用drools
12 | * /resources/META-INF/kmodule.xml
13 | */
14 | public class rule2 {
15 |
16 | public static void main(final String[] args) {
17 | KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
18 | System.out.println(kc.verify().getMessages().toString());
19 | execute(kc);
20 | }
21 |
22 | private static void execute(KieContainer kc) {
23 | KieSession ksession = kc.newKieSession("rule2KS");
24 |
25 | Person p1 = new Person(35, "xu", "handsome");
26 | Person p2 = new Person(30, "hua", "handsome");
27 |
28 | ksession.insert(p1);
29 | ksession.insert(p2);
30 |
31 | ksession.fireAllRules();
32 |
33 | QueryResults results = ksession.getQueryResults("people2");
34 | System.out.println("we have " + results.size() + " people over the age of 30");
35 |
36 | System.out.println("These people are are over 30:");
37 |
38 | for (QueryResultsRow row : results) {
39 | Person person = (Person) row.get("person");
40 | System.out.println(person.getName() + "\n");
41 | }
42 |
43 | ksession.dispose();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/service/RuleTableService.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.service;
2 |
3 |
4 | import org.apache.logging.log4j.LogManager;
5 | import org.apache.logging.log4j.Logger;
6 | import org.drools.decisiontable.SpreadsheetCompiler;
7 | import org.kie.internal.io.ResourceFactory;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.io.File;
11 | import java.io.InputStream;
12 |
13 | @Service
14 | public class RuleTableService {
15 | private static Logger logger = LogManager.getLogger();
16 | /**
17 | * 默认规则文件所在路径
18 | */
19 | private static final String RULES_PATH = "tables";
20 |
21 | public String getRuleTable() {
22 | //把excel翻译成drl文件
23 | SpreadsheetCompiler compiler = new SpreadsheetCompiler();
24 | String rules = compiler.compile(ResourceFactory.newClassPathResource(RULES_PATH + File.separator + "rule.xlsx", "UTF-8"), "rule-table");
25 | System.out.println(rules);
26 | return rules;
27 | }
28 |
29 | /**
30 | * 通过决策表文件流获取rule
31 | *
32 | * @param inputStream 决策表文件流
33 | * @return rule
34 | */
35 | public String getRuleTable(InputStream inputStream) {
36 | //把excel翻译成drl文件
37 | SpreadsheetCompiler compiler = new SpreadsheetCompiler();
38 | String rules = compiler.compile(ResourceFactory.newInputStreamResource(inputStream, "UTF-8"), "rule-table");
39 | logger.info("get rule from xls:" + rules);
40 | return rules;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/service/RulesService.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.service;
2 |
3 |
4 | import com.xu.drools.bean.Person;
5 | import com.xu.drools.bean.Rules;
6 | import com.xu.drools.common.bean.ExceptionType;
7 | import com.xu.drools.common.exception.BusinessException;
8 | import com.xu.drools.dao.RulesDao;
9 | import org.kie.api.KieBase;
10 | import org.kie.api.KieServices;
11 | import org.kie.api.builder.KieBuilder;
12 | import org.kie.api.builder.KieFileSystem;
13 | import org.kie.api.builder.Results;
14 | import org.kie.api.runtime.KieContainer;
15 | import org.kie.api.runtime.KieSession;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.stereotype.Service;
18 |
19 | @Service
20 | public class RulesService {
21 |
22 | @Autowired
23 | private RulesDao rulesDao;
24 | /**
25 | * 动态获取KieSession
26 | *
27 | * @param rules rule
28 | * @return KieSession
29 | */
30 | public KieSession getKieSession(String rules) {
31 | KieServices kieServices = KieServices.Factory.get();
32 | KieFileSystem kfs = kieServices.newKieFileSystem();
33 | kfs.write("src/main/resources/rules/rules.drl", rules.getBytes());
34 | KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
35 | Results results = kieBuilder.getResults();
36 | if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
37 | System.out.println(results.getMessages());
38 | throw new BusinessException(300003,results.getMessages().toString(),4);
39 | }
40 | KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
41 | KieBase kieBase = kieContainer.getKieBase();
42 |
43 | return kieBase.newKieSession();
44 | }
45 |
46 | /**
47 | * 动态加载已经部署的rule
48 | *
49 | * @param id rule id
50 | * @param t 对象
51 | * @return 结果对象
52 | */
53 | public Person getRulesWrite(Integer id, Person t) {
54 | String rules;
55 | Rules ru = rulesDao.getById(id);
56 | if (ru != null && ru.getRule() != null) {
57 | rules = ru.getRule();
58 | } else throw new BusinessException(ExceptionType.RULE_IS_NULL);
59 |
60 | KieServices kieServices = KieServices.Factory.get();
61 | KieFileSystem kfs = kieServices.newKieFileSystem();
62 | kfs.write("src/main/resources/rules/rules.drl", rules.getBytes());
63 | KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
64 | Results results = kieBuilder.getResults();
65 | if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
66 | System.out.println(results.getMessages());
67 | throw new IllegalStateException("### errors ###");
68 | }
69 | KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
70 | KieBase kieBase = kieContainer.getKieBase();
71 | KieSession ksession = kieBase.newKieSession();
72 |
73 | ksession.insert(t);
74 | ksession.fireAllRules();
75 | return t;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/web/ComplexProblem.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.web;
2 |
3 | import org.springframework.web.bind.annotation.RequestMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | /**
7 | * 使用drools来解决复杂问题
8 | */
9 | @RequestMapping(value = "/rules")
10 | @RestController
11 | public class ComplexProblem {
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/xu/drools/web/RulesController.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools.web;
2 |
3 |
4 | import com.google.gson.Gson;
5 | import com.xu.drools.bean.Person;
6 | import com.xu.drools.common.exception.JsonResponse;
7 | import com.xu.drools.dao.RulesDao;
8 | import com.xu.drools.service.RuleTableService;
9 | import com.xu.drools.service.RulesService;
10 | import io.swagger.annotations.ApiImplicitParam;
11 | import io.swagger.annotations.ApiImplicitParams;
12 | import io.swagger.annotations.ApiOperation;
13 | import org.kie.api.runtime.KieSession;
14 | import org.springframework.beans.factory.annotation.Autowired;
15 | import org.springframework.web.bind.annotation.RequestMapping;
16 | import org.springframework.web.bind.annotation.RequestMethod;
17 | import org.springframework.web.bind.annotation.RequestParam;
18 | import org.springframework.web.bind.annotation.RestController;
19 | import org.springframework.web.multipart.MultipartFile;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 |
24 | /**
25 | * Drools的基本用法,动态规则+决策表
26 | */
27 | @RequestMapping(value = "/rules")
28 | @RestController
29 | public class RulesController {
30 |
31 | @Autowired
32 | private RulesService rulesService;
33 | @Autowired
34 | private RuleTableService ruleTableService;
35 | @Autowired
36 | private RulesDao rulesDao;
37 |
38 | @ApiOperation(value = "验证规则是否合法",notes = verify)
39 | @RequestMapping(value = "/verify", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
40 | public JsonResponse ruleVerify(@RequestParam(value = "rule") String rule,
41 | @RequestParam(value = "data") String json) {
42 | KieSession kieSession = rulesService.getKieSession(rule);
43 | Gson gson = new Gson();
44 | Person person = gson.fromJson(json, Person.class);
45 | kieSession.insert(person);
46 | int rules=kieSession.fireAllRules();
47 | System.out.println(rules);
48 | kieSession.dispose();
49 | return new JsonResponse(person);
50 | }
51 |
52 |
53 | @ApiOperation(value = "添加规则")
54 | @ApiImplicitParams({
55 | @ApiImplicitParam(name = "rule", dataType = "String", required = true, value = "规则"),
56 | @ApiImplicitParam(name = "name", dataType = "String", required = true, value = "规则名称")})
57 | @RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
58 | public JsonResponse ruleAdd(@RequestParam String rule, @RequestParam String name) {
59 | rulesDao.setRule(name, rule);
60 | return new JsonResponse("");
61 | }
62 |
63 | @ApiOperation(value = "规则列表")
64 | @RequestMapping(value = "/list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
65 | public JsonResponse getRuleList() {
66 | return new JsonResponse(rulesDao.getRuleList());
67 | }
68 |
69 |
70 | @ApiOperation(value = "规则结果")
71 | @RequestMapping(value = "/result", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
72 | public JsonResponse getResult(@RequestParam("id") Integer id, @RequestParam("json") String json) {
73 | Gson gson = new Gson();
74 | Person person = gson.fromJson(json, Person.class);
75 | return new JsonResponse(rulesService.getRulesWrite(id, person));
76 | }
77 |
78 | @ApiOperation(value = "决策表转换")
79 | @ApiImplicitParam(name = "file", dataType = "MultipartFile", required = true, value = "决策表xls")
80 | @RequestMapping(value = "/getRuleXls", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
81 | public JsonResponse getRuleXls(@RequestParam(value = "file") MultipartFile file) throws IOException {
82 | InputStream inputStream = file.getInputStream();
83 | String rule = ruleTableService.getRuleTable(inputStream);
84 | try {
85 | KieSession kieSession = rulesService.getKieSession(rule);
86 | kieSession.insert(new Person());
87 | } catch (Exception e) {
88 | e.printStackTrace();
89 | return new JsonResponse(e);
90 | }
91 | return new JsonResponse(rule);
92 | }
93 |
94 | @ApiOperation(value = "删除规则")
95 | @ApiImplicitParam(name = "id", dataType = "Integer", required = true, value = "规则编号")
96 | @RequestMapping(value = "/delete", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
97 | public JsonResponse delete(@RequestParam Integer id) {
98 | return new JsonResponse(rulesDao.deleteRule(id));
99 | }
100 |
101 | @ApiOperation(value = "修改规则")
102 | @ApiImplicitParams({
103 | @ApiImplicitParam(name = "rule", dataType = "String", required = true, value = "规则"),
104 | @ApiImplicitParam(name = "id", dataType = "Integer", required = true, value = "规则id"),
105 | @ApiImplicitParam(name = "name", dataType = "String", required = true, value = "规则名称")})
106 | @RequestMapping(value = "/ruleUpdate", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
107 | public JsonResponse ruleUpdate(@RequestParam String rule, @RequestParam Integer id, @RequestParam String name) {
108 | return new JsonResponse(rulesDao.updateRule(id, name, rule));
109 | }
110 |
111 | private final static String verify="规则:package com.xu.drools;\n" +
112 | "import com.xu.drools.bean.Person;\n" +
113 | "rule \"2\"\n" +
114 | "\twhen\n" +
115 | " $p : Person(age < 30);\n" +
116 | " then\n" +
117 | "\t\tSystem.out.println(\"hello, young xu2!\");\n" +
118 | "\t\t$p.setDesc(\"young \"+$p.getName());\n" +
119 | "\t\tretract($p)\n" +
120 | "end"+" 数据实体:{\n" +
121 | " \"age\":18,\n" +
122 | " \"name\":\"xu\",\n" +
123 | " \"desc\":\"帅\"\n" +
124 | "}";
125 | }
126 |
127 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/kmodule.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | spring:
4 | datasource:
5 | driver-class-name: com.mysql.jdbc.Driver
6 | url: jdbc:mysql://localhost:3306/xus?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&noAccessToProcedureBodies=true
7 | username: root
8 | password: 4321
9 | type: com.alibaba.druid.pool.DruidDataSource
10 | initialSize: 5
11 | minIdle: 5
12 | maxActive: 50
13 | maxWait: 1000
14 | filters: stat,wall,log4j
--------------------------------------------------------------------------------
/src/main/resources/com/xu/drools/rule/complexProblem/golfer.drl:
--------------------------------------------------------------------------------
1 | package com.xu.drools
2 |
3 | import com.xu.drools.bean.Golfer;
4 |
5 | rule "find solution"
6 | when
7 | //1.高尔夫球员Fred,目前不知道他的位置和衣服颜色
8 | $fred : Golfer( name == "Fred" )
9 |
10 | //3.Joe排在第2个位置
11 | $joe : Golfer( name == "Joe",
12 | position == 2,
13 | position != $fred.position,
14 | color != $fred.color )
15 |
16 | //4.Bob穿着格子短裤
17 | $bob : Golfer( name == "Bob",
18 | position != $fred.position,
19 | position != $joe.position,
20 | color == "plaid",
21 | color != $fred.color,
22 | color != $joe.color )
23 |
24 | //5.Tom没有排在第1位或第4位,也没有穿橙色衣服
25 | $tom : Golfer( name == "Tom",
26 | position != 1,
27 | position != 4,
28 | position != $fred.position,
29 | position != $joe.position,
30 | position != $bob.position,
31 | color != "orange",
32 | color != $fred.color,
33 | color != $joe.color,
34 | color != $bob.color )
35 |
36 | //2.Fred右边紧挨着的球员穿蓝色衣服
37 | Golfer( position == ( $fred.position + 1 ),
38 | color == "blue",
39 | this in ( $joe, $bob, $tom ) )
40 |
41 | then
42 | System.out.println( "Fred " + $fred.getPosition() + " " + $fred.getColor() );
43 | System.out.println( "Joe " + $joe.getPosition() + " " + $joe.getColor() );
44 | System.out.println( "Bob " + $bob.getPosition() + " " + $bob.getColor() );
45 | System.out.println( "Tom " + $tom.getPosition() + " " + $tom.getColor() );
46 | end
--------------------------------------------------------------------------------
/src/main/resources/com/xu/drools/rule/complexProblem/ming.drl:
--------------------------------------------------------------------------------
1 | package com.xu.drools
2 |
3 | import com.xu.drools.bean.XiaoMing;
4 |
5 |
6 | // 小明喝汽水问题
7 | // 1元钱一瓶汽水,喝完后两个空瓶换一瓶汽水,问:小明有20元钱,最多可以喝到几瓶汽水?
8 | // 规则1:1元钱一瓶汽水
9 | // 规则2:两个空瓶换一瓶汽水
10 |
11 | //规则1:1元钱一瓶汽水。有钱就买水,空瓶+1,钱-1,喝水+1;
12 | rule "rule1"
13 | salience 3
14 | when
15 | $m:XiaoMing(money>0);
16 | then
17 | System.out.println("有钱即可喝水,钱:"+$m.getMoney());
18 | $m.setBottle($m.getBottle()+1);
19 | $m.setMoney($m.getMoney()-1);
20 | $m.setDrink($m.getDrink()+1);
21 | update($m)
22 | end
23 |
24 | //规则2:两个空瓶换一瓶汽水。有空瓶就换钱,空瓶-2,钱+1;
25 | rule "rule2"
26 | salience 2
27 | when
28 | $m:XiaoMing(bottle>=2);
29 | then
30 | System.out.println("有瓶子就换钱,瓶子:"+$m.getBottle());
31 | $m.setBottle($m.getBottle()-2);
32 | $m.setMoney($m.getMoney()+1);
33 | update($m)
34 | end
35 |
36 | //规则3,打印已经喝掉的数量
37 | rule "rule3"
38 | salience 1
39 | when
40 | $m:XiaoMing();
41 | then
42 | System.out.println("总共喝掉:"+$m.getDrink());
43 | end
--------------------------------------------------------------------------------
/src/main/resources/com/xu/drools/rule/complexProblem/world.drl:
--------------------------------------------------------------------------------
1 | package com.xu.drools
2 |
3 | import com.xu.drools.bean.Student;
4 | import com.xu.drools.bean.World
5 |
6 | rule "find jia1"
7 | salience 2
8 | when
9 | $jia1 : Student(name == "jia",word1=="A",word2=="C",desc1=="2",desc2!="3")
10 | then
11 | insert( new World($jia1.getDesc1(),0,$jia1.getDesc2()) );
12 | end
13 |
14 | rule "find jia2"
15 | salience 2
16 | when
17 | $jia2 : Student(name == "jia",word1=="A",word2=="C",desc1!="2",desc2=="3")
18 | then
19 | insert( new World($jia2.getDesc1(),0,$jia2.getDesc2()) );
20 | end
21 |
22 | rule "find yi1"
23 | salience 3
24 | when
25 | $yi1 : Student(name == "yi",word1=="A",word2=="B",desc1=="1",desc2!="3");
26 | $w : World(a==$yi1.getDesc1())
27 | then
28 | $w.setB($yi1.getDesc2());
29 | update($w)
30 | end
31 |
32 | rule "find yi2"
33 | salience 3
34 | when
35 | $yi2 : Student(name == "yi",word1=="A",word2=="B",desc1=="1",desc2!="3")
36 | $w : World(a==$yi2.getDesc1())
37 | then
38 | $w.setB($yi2.getDesc2());
39 | update($w)
40 | end
41 |
42 |
43 | rule "find bing1"
44 | salience 4
45 | when
46 | $bing1 : Student(name == "bing",word1=="A",word2=="B",desc1=="3",desc2!="2")
47 | $w : World(a==$bing1.getDesc1(),b==$bing1.getDesc2())
48 | then
49 | System.out.println("-------"+$w.toString());
50 | end
51 |
52 |
53 | rule "find bing2"
54 | salience 4
55 | when
56 | $bing2 : Student(name == "bing",word1=="A",word2=="B",desc1!="3",desc2=="2")
57 | $w : World(a==$bing2.getDesc1(),b==$bing2.getDesc2())
58 | then
59 | System.out.println("-------"+$w.toString());
60 | end
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/main/resources/com/xu/drools/rule/honestpolitician/HonestPolitician.drl:
--------------------------------------------------------------------------------
1 | package com.xu.drools
2 |
3 | import com.xu.drools.bean.Politician;
4 | import com.xu.drools.bean.Hope;
5 |
6 | rule "We have an honest Politician"
7 | salience 10
8 | when
9 | exists( Politician( honest == true ) )
10 | then
11 | insertLogical( new Hope() );
12 | end
13 |
14 | rule "Hope Lives"
15 | salience 10
16 | when
17 | exists( Hope() )
18 | then
19 | System.out.println("Hurrah!!! Democracy Lives");
20 | end
21 |
22 | rule "Hope is Dead"
23 | when
24 | not( Hope() )
25 | then
26 | System.out.println( "We are all Doomed!!! Democracy is Dead" );
27 | end
28 |
29 | rule "Corrupt the Honest"
30 | when
31 | politician : Politician( honest == true )
32 | exists( Hope() )
33 | then
34 | System.out.println( "I'm an evil corporation and I have corrupted " + politician.getName() );
35 | modify( politician ) {
36 | setHonest( false )
37 | }
38 | end
39 |
40 |
--------------------------------------------------------------------------------
/src/main/resources/com/xu/drools/rule/rule1/rule1.drl:
--------------------------------------------------------------------------------
1 | package com.xu.drools;
2 | import com.xu.drools.bean.Person;
3 | rule "2"
4 | when
5 | $p : Person(age > 30);
6 | then
7 | System.out.println("hello, young xu2!");
8 | end
9 |
10 | query "people2"
11 | person : Person( age > 30 )
12 | end
--------------------------------------------------------------------------------
/src/main/resources/com/xu/drools/rule/rule2/rule2.drl:
--------------------------------------------------------------------------------
1 | package com.xu.drools;
2 | import com.xu.drools.bean.Person;
3 | rule "2"
4 | when
5 | $p : Person(age > 30);
6 | then
7 | System.out.println("hello, young xu2!");
8 | end
9 |
10 | query "people2"
11 | person : Person( age > 30 )
12 | end
--------------------------------------------------------------------------------
/src/main/resources/drools_rule.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat MySQL Data Transfer
3 |
4 | Source Server : MyDB
5 | Source Server Version : 50709
6 | Source Host : localhost:3306
7 | Source Database : xus
8 |
9 | Target Server Type : MYSQL
10 | Target Server Version : 50709
11 | File Encoding : 65001
12 |
13 | Date: 2017-08-29 20:17:26
14 | */
15 |
16 | SET FOREIGN_KEY_CHECKS=0;
17 |
18 | -- ----------------------------
19 | -- Table structure for drools_rule
20 | -- ----------------------------
21 | DROP TABLE IF EXISTS `drools_rule`;
22 | CREATE TABLE `drools_rule` (
23 | `id` int(11) NOT NULL AUTO_INCREMENT,
24 | `name` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL,
25 | `rule` mediumtext CHARACTER SET utf8mb4,
26 | `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
27 | `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
28 | `visible` int(11) DEFAULT NULL,
29 | PRIMARY KEY (`id`)
30 | ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
31 |
32 | -- ----------------------------
33 | -- Records of drools_rule
34 | -- ----------------------------
35 | INSERT INTO `drools_rule` VALUES ('3', 'rule_005', 'package com.xu.drools;\r\nimport com.xu.drools.bean.Person;\r\nrule \"2\"\r\n when\r\n $p : Person(age < 30);\r\n then\r\n System.out.println(\"hello, young xu2!\");\r\n $p.setDesc(\"young \"+$p.getName());\r\n retract($p)\r\nend', '2017-01-17 10:43:14', '2017-08-29 20:15:37', '1');
36 |
--------------------------------------------------------------------------------
/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ????
5 | %clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%wEx
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/main/resources/tables/rule.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MyHerux/drools-springboot/df2f7bda6fd963b882bce0eda458d92d4fb57600/src/main/resources/tables/rule.xlsx
--------------------------------------------------------------------------------
/src/test/java/com/xu/drools/DroolsSpringbootApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.xu.drools;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class DroolsSpringbootApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------