使用drools-7.73.0.Final实现规则匹配的简单案例
1、案例业务规则说明
在一般的商城系统中,订单收到货签收完成后可以参与评价订单,商城会针对好评赠送相应的积分。
如可以定义金牌、银牌、铜牌会员,分别评论商品的字数多少,是否上传实物拍照,给予多少颗星的评价等多个维度判断给用户赠送合适的积分。
假定一个评论送积分的规则如下
会员级别 | 级别码 | 3星 | 4星 | 5星 |
---|---|---|---|---|
金牌 | 30 | 100积分 | 300积分 | 500积分 |
银牌 | 20 | 50积分 | 250积分 | 400积分 |
铜牌 | 10 | 30积分 | 200积分 | 300积分 |
2、案例演示代码
使用spring-boot:2.7.2+drools-7.73.0.Final
完成演示
- 2.1、配置文件pom.xml文件中drools依赖包内容如下
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
<version>7.73.0.Final</version>
</dependency>
- 2.2、新建配置文件kmodule.xml(在目录resources/META-INF/kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="kbase" packages="rules" default="true">
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>
此文件默认定义,可以不修改
- 2.3、编写规则文件comment_score.drl(在目录resources/rules/comment_score.drl)
package rules;
import com.mixfate.drools.model.Comment
rule "comment_score_30_5"
when
$comment: Comment(account.level==30 && star==5)
then
$comment.setScore(500);
end
rule "comment_score_30_4"
when
$comment: Comment(account.level==30 && star==4)
then
$comment.setScore(300);
end
rule "comment_score_30_3"
when
$comment: Comment(account.level==30 && star==3)
then
$comment.setScore(100);
end
注意:规则文件是以drl为后缀命名的,为了在项目中清晰地区分各种业务规则,最好是遵循一定的规范定义规则,不然到后期会非常混乱。规则匹配成功时将setScore设置积分数量。
- 2.3、编写Java代码
DroolsApplication.java
------
package com.mixfate.drools;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class DroolsApplication {
public static void main(String[] args) {
SpringApplication.run(DroolsApplication.class, args);
}
@Bean
public KieContainer kieContainer() {
KieServices service = KieServices.Factory.get();
return service.newKieClasspathContainer();
}
}
Comment.java
------
package com.mixfate.drools.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Comment {
private int star;
private Account account;
private int score;
}
Account.java
------
package com.mixfate.drools.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Account {
private int level;
}
代码非常简单,定义一个Comment对象,里面包含了账号信息、评论的星数及赠送的积分信息。
- 2.4、编写Java测试代码
@Autowired
private KieContainer kieContainer;
@Test
public void comment() {
KieSession kieSession = kieContainer.newKieSession();
Comment comment = new Comment();
Account account = new Account();
account.setLevel(30);
comment.setStar(new Random().nextInt(3) + 3);
comment.setAccount(account);
System.out.println(JSON.toJSONString(comment));
// 插入comment
kieSession.insert(comment);
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("comment_score"));
//清除会话
kieSession.dispose();
System.out.println(JSON.toJSONString(comment));
}
在测试代码中使用newKieSession创建新的session,注意在使用完成后需要使用dispose方法将session清除。在fireAllRules时传入一个规则的前缀,可以按这个规范将同一个规则文件内的规则命名成相同的前缀,通过此过滤器限定规则的范围。