0x0.基于Drools实现动态接口
项目已上传至github:
后端demo:https://github.com/gx304419380/drools-demo
前端:https://github.com/gx304419380/dynamic-drools-web
jar包:https://github.com/gx304419380/dynamic-rule
项目已经上传至maven中央仓库:
<dependency>
<groupId>com.github.gx304419380</groupId>
<artifactId>dynamic-rule</artifactId>
<version>1.0.3</version>
</dependency>
0x1. 核心原理
利用Drools引擎的动态编译功能,根据规则字符串生成一个规则容器,进而获取session执行规则;
我们会在session中插入必要的工具类,例如spring的容器,jdbcTemplate等
KieContainer container = new KieHelper().addContent(rule, DRL).getKieContainer();
KieSession session = container.newKieSession();
//设置日志和spring容器
session.insert(log);
session.insert(context);
session.insert(jdbcTemplate);
其中规则类似如下,可以调用jdbc,redis,restTemplate以及获取Spring容器中的bean:
rule "discount_rule_4"
when
param: Param()
r: RuleResult()
log: Logger()
context: ApplicationContext()
jdbc: JdbcTemplate()
then
log.info("drools execute, param={}", param);
TestService t = context.getBean(TestService.class);
String res = t.test("123456");
log.info("test spring context: {}", res);
List<Rule> list = jdbc.query("select * from tb_rule", new BeanPropertyRowMapper<>(Rule.class));
log.info("rule list = {}", list);
end
0x2.使用方法
2.1 引入maven依赖并配置
<dependency>
<groupId>com.github.gx304419380</groupId>
<artifactId>dynamic-rule</artifactId>
<version>1.0.3</version>
</dependency>
在项目中添加@EnableDynamicRule
注解,会引入相关配置,例如:
@SpringBootApplication
@EnableDynamicRule
public class MybatisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisDemoApplication.class, args);
}
}
2.2 配置数据库
例如:
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
2.3 启动项目
启动项目后,可以看到项目自动建立了一个tb_rule
的表,用于保存用户配置的规则;
访问项目路径/dynamic-rule会自动跳转到动态规则配置页面,如下:
可以看到用户配置的动态规则列表
2.4 新增一个规则:
点击新增按钮进入新增规则页面,填写规则名称,规则说明以及规则代码即可;
其中drools规则代码可以在IDEA下编辑,因为IDEA天然支持DROOLS语法,有代码高亮和自动填充功能,很方便:
2.5 规则接口测试
规则编写完成后可以进行规则测试,点击右边测试按钮弹出测试框:
填写参数点击提交即可测试接口。
0x3. 使用场景:
对于易变的业务逻辑,比如经常需要定制的部分,可以将他们卸载规则中,然后使用动态接口或者DynamicService
进行调用即可,只需要知道规则ID就能调用;
后续会优化规则调用方式为按名称调用,方便用户自定义规则名称进行调用。