栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Drools7 动态更新规则

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Drools7 动态更新规则

动态更新规则

上一章节讲述了 Drools7 和 Springboot2 集成使用,集成工作相对简单、可以快速开发。但是缺点也很明显,规则和配置文件绑定在项目中(耦合度太高)。如果你不需要修改规则文件,这种方式还是可以采纳的。此篇讲述如何从数据库中加载规则文件,动态加载更新规则。

KieHelper

Drools 中提供了 KieHelper ,可以动态添加规则,并且创建新的 kieContainer 返回。

// 借助 kieHelper 添加规则
KieHelper kieHelper = new KieHelper();
// 动态添加规则内容
kieHelper.addContent(content, ResourceType.DRL);
// 校验规则是否异常
Results results = kieHelper.verify();
if (results.hasMessages(Message.Level.ERROR)) {
    System.out.println(results.getMessages());
    throw new IllegalStateException("### errors ###");
}
// 重置 kieContainer
kieContainer = kieHelper.getKieContainer();
更新规则实现 添加依赖


    mysql
    mysql-connector-java
    5.1.43


    com.baomidou
    mybatis-plus-boot-starter
    3.0.5



    org.kie
    kie-spring
    ${drools.version}
    
        
        
            org.springframework
            spring-tx
        
        
            org.springframework
            spring-beans
        
        
            org.springframework
            spring-core
        
        
            org.springframework
            spring-context
        
    

表结构设计

两条规则分别对 Person 名字和年龄进行判断;
第一条:如果name=“bob” 则打印规则名称,规则包名,和 name;
第二条:如果name=“bob” 且年龄是25和65之间则打印 is a work person;

DROP TABLE IF EXISTS `rule`;
CREATE TABLE `rule`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `rule` VALUES (1, '1.find target person', 'package rules.rulesrnrnimport com.skystep.drools.person.PersonRuleActionrnimport com.skystep.drools.person.entity.Personrnimport com.skystep.drools.person.service.PersonServicernimport com.skystep.drools.person.service.PersonServiceImplrnrn// 根据名字匹配指定的人rnrule "1.find target person"rn    whenrn        $p : Person( name == "bob" )rn    thenrn        PersonRuleAction.doParse($p, drools.getRule());rn        System.out.println(" Rule name is [" + drools.getRule().getName() + "] ");rn        System.out.println(" Rule package is [" + drools.getRule().getPackageName() + "] ");rn        PersonService personService = new PersonServiceImpl();rn        personService.hello(" 我的名字是: " + $p.getName());rnend');
INSERT INTO `rule` VALUES (2, '2.find the work person', 'package rules.rulesrnrnimport com.skystep.drools.person.PersonRuleActionrnimport com.skystep.drools.person.entity.Personrnimport com.skystep.drools.person.service.PersonServicernimport com.skystep.drools.person.service.PersonServiceImplrnrn// 根据年龄匹配找到打工人rnrule "2.find the work person"rn    whenrn        $p : Person( age >= 25 && age < 65 )rn    thenrn        System.out.println( $p + " is a work person!" );rnend');

默认配置 Drools
@Configuration
public class RuleEngineConfig {
    private static final String RULES_PATH = "rules/";

    @Bean
    @ConditionalOnMissingBean(KieFileSystem.class)
    public KieFileSystem kieFileSystem() throws IOException {
        KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
        for (Resource file : getRuleFiles()) {
            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
        }
        return kieFileSystem;
    }

    private Resource[] getRuleFiles() throws IOException {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
    }

    @Bean
    @ConditionalOnMissingBean(KieContainer.class)
    public KieContainer kieContainer() throws IOException {
        final KieRepository kieRepository = getKieServices().getRepository();

        kieRepository.addKieModule(new KieModule() {
            @Override
            public ReleaseId getReleaseId() {
                return kieRepository.getDefaultReleaseId();
            }
        });

        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
        kieBuilder.buildAll();

        return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
    }

    private KieServices getKieServices() {
        return KieServices.Factory.get();
    }

    @Bean
    @ConditionalOnMissingBean(KieBase.class)
    public KieBase kieBase() throws IOException {
        return kieContainer().getKieBase();
    }

    // 不能反复被使用,释放资源后需要重新获取。
    // @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    @ConditionalOnMissingBean(KieSession.class)
    public KieSession kieSession() throws IOException {
        return kieContainer().newKieSession();
    }

    @Bean
    @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
    public KModuleBeanFactoryPostProcessor kiePostProcessor() {
        return new KModuleBeanFactoryPostProcessor();
    }
}
Drools 动态加载规则

RuleService 提供 getRules 方法从数据库中获取所有的规则,循环加载到 kieHelper。Spring 启动注入 RuleEngineService 时会提前初始化,执行 reload 函数。因此此时内容中存在的规则是从数据库中加载的规则。

@Service
@Slf4j
public class RuleEngineService {

    @Autowired
    private KieContainer kieContainer;

    // 规则服务
    @Autowired
    RuleService ruleService;

    @PostConstruct
    public void init() {
        reload();
    }

    public KieContainer getKieContainer() {
        return kieContainer;
    }


    public void reload() {
        // 借助 kieHelper 添加规则
        KieHelper kieHelper = new KieHelper();
        // 从数据库中获取所有的规则
        List rules = ruleService.getRules();
        if (!CollectionUtils.isEmpty(rules)) {
            // 循环加载所有的规则
            for (Rule rule : rules) {
                String content = rule.getContent();
                kieHelper.addContent(content, ResourceType.DRL);
            }
        }
        // 校验规则是否异常
        Results results = kieHelper.verify();

        if (results.hasMessages(Message.Level.ERROR)) {
            System.out.println(results.getMessages());
            throw new IllegalStateException("### errors ###");
        }
        // 重置容器
        kieContainer = kieHelper.getKieContainer();
    }
}
添加接口
@RestController
@RequestMapping("rule")
public class PersonRuleController {
    @Autowired
    private RuleEngineService ruleEngineService;

    @PostMapping("test")
    public void fireAllRules4One(@RequestBody Person person) {
        KieSession kSession = ruleEngineService.getKieContainer().newKieSession();
        try {
            kSession.insert(person);
            kSession.fireAllRules(new RuleNameEqualsAgendaFilter(""));
        } finally {
            kSession.dispose();
        }
        return;
    }

    @GetMapping("reload")
    public void reload() {
        ruleEngineService.reload();
    }
}
验证

POST /rule/test,请求参数:

{"name": "bob"}
Rule name is [1.find target person] 
Rule package is [rules.rules] 
2022-07-02 23:31:58.580  INFO 23540 --- [nio-8080-exec-6] c.s.d.person.service.PersonServiceImpl   :  我的名字是: bob

命中了数据库中的第一条规则。name=“bob”,

POST /rule/test,请求参数:

{"name": "bob", "age": 33}
Rule name is [1.find target person] 
Rule package is [rules.rules] 
2022-07-02 23:39:49.991  INFO 23540 --- [nio-8080-exec-9] c.s.d.person.service.PersonServiceImpl   :  我的名字是: bob
Person(name=bob, age=33) is a work person!

命中了数据库中的两条记录

动态添加规则

数据库增加一条规则,判断名称是否是 skystep, 如果name=“skystep” 则打印规则名称,规则包名,和 name。

INSERT INTO `rule` VALUES (3, '3.find target person', 'package rules.rulesrnrnimport com.skystep.drools.person.PersonRuleActionrnimport com.skystep.drools.person.entity.Personrnimport com.skystep.drools.person.service.PersonServicernimport com.skystep.drools.person.service.PersonServiceImplrnrn// 根据名字匹配指定的人rnrule "3.find target person"rn    whenrn        $p : Person( name == "skystep" )rn    thenrn        PersonRuleAction.doParse($p, drools.getRule());rn        System.out.println(" Rule name is [" + drools.getRule().getName() + "] ");rn        System.out.println(" Rule package is [" + drools.getRule().getPackageName() + "] ");rn        PersonService personService = new PersonServiceImpl();rn        personService.hello(" 我的名字是: " + $p.getName());rn end');

GET /rule/reload 重新加载规则,

POST /rule/test,请求参数:

{"name": "skystep"}
Rule name is [3.find target person] 
 Rule package is [rules.rules] 
2022-07-03 00:00:49.148  INFO 23540 --- [nio-8080-exec-2] c.s.d.person.service.PersonServiceImpl   :  我的名字是: skystep

命中了数据库中的第条3规则,说明动态添加的第三条规则已经加载到内存,并且成功匹配。

源码下载

https://download.csdn.net/download/skystep/85870731
Drools7 + Springboot2 动态更新规则。
规则存储到数据库MYSQL,动态从数据库中获取规则进行加载。
运行前请自行修改MYSQL配置

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1006071.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号