《Drools7.0.0.Final规则引擎教程》Springboot+规则重新加载详解编程语言

在《Drools7.0.0.Final规则引擎教程》之Springboot集成中介绍了怎样将Drools与Springboot进行集成,本篇博客介绍一下集成之后,如何实现从数据库读取规则并重新加载规则的简单demo。因本章重点介绍的是Drools相关操作的API,所以将查询数据库部分的操作省略,直接使用数据库查询出的规则代码来进行规则的重新加载。另外,此示例采用访问一个http请求来进行重新加载,根据实际需要可考虑定时任务进行加载等扩展方式。最终的使用还是要结合具体业务场景来进行分析扩展。

整体项目结构

这里写图片描述
上图是基于intellij maven的项目结构。其中涉及到springboot的Drools集成配置类,重新加载规则类。一些实体类和工具类。下面会抽出比较重要的类进行分析说明。

DroolsAutoConfiguration

@Configuration public class DroolsAutoConfiguration { 
 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() { public ReleaseId getReleaseId() { return kieRepository.getDefaultReleaseId(); 
            } 
        }); 
 
        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem()); 
        kieBuilder.buildAll(); 
 
        KieContainer kieContainer = getKieServices().newKieContainer(kieRepository.getDefaultReleaseId()); 
        KieUtils.setKieContainer(kieContainer); return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId()); 
    } 
 private KieServices getKieServices() { return KieServices.Factory.get(); 
    } 
 @Bean @ConditionalOnMissingBean(KieBase.class) public KieBase kieBase() throws IOException { return kieContainer().getKieBase(); 
    } 
 @Bean @ConditionalOnMissingBean(KieSession.class) public KieSession kieSession() throws IOException { 
        KieSession kieSession = kieContainer().newKieSession(); 
        KieUtils.setKieSession(kieSession); return kieSession; 
    } 
 @Bean @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class) public KModuleBeanFactoryPostProcessor kiePostProcessor() { return new KModuleBeanFactoryPostProcessor(); 
    } 
}

此类主要用来初始化Drools的配置,其中需要注意的是对KieContainer和KieSession的初始化之后都将其设置到KieUtils类中。

KieUtils

KieUtils类中存储了对应的静态方法和静态属性,供其他使用的地方获取和更新。

public class KieUtils { 
 private static KieContainer kieContainer; 
 private static KieSession kieSession; 
 public static KieContainer getKieContainer() { return kieContainer; 
    } 
 public static void setKieContainer(KieContainer kieContainer) { 
        KieUtils.kieContainer = kieContainer; 
        kieSession = kieContainer.newKieSession(); 
    } 
 public static KieSession getKieSession() { return kieSession; 
    } 
 public static void setKieSession(KieSession kieSession) { 
        KieUtils.kieSession = kieSession; 
    } 
}

ReloadDroolsRules

提供了reload规则的方法,也是本篇博客的重点之一,其中从数据库读取的规则代码直接用字符串代替,读者可自行进行替换为数据库操作。

@Service 
public class ReloadDroolsRules { 
 public void reload() throws UnsupportedEncodingException { 
        KieServices kieServices = KieServices.Factory.get(); 
        KieFileSystem kfs = kieServices.newKieFileSystem(); 
        kfs.write("src/main/resources/rules/temp.drl", loadRules()); 
        KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); 
        Results results = kieBuilder.getResults(); if (results.hasMessages(Message.Level.ERROR)) { 
            System.out.println(results.getMessages()); throw new IllegalStateException("### errors ###"); 
        } 
 
        KieUtils.setKieContainer(kieServices.newKieContainer(getKieServices().getRepository().getDefaultReleaseId())); 
        System.out.println("新规则重载成功"); 
    } 
 private String loadRules() { // 从数据库加载的规则 return "package plausibcheck.adress/n/n import com.neo.drools.model.Address;/n import com.neo.drools.model.fact.AddressCheckResult;/n/n rule /"Postcode 6 numbers/"/n/n    when/n  then/n        System.out.println(/"规则2中打印日志:校验通过!/");/n end"; 
 
    } 
 private KieServices getKieServices() { return KieServices.Factory.get(); 
    } 
 
}

TestController

提供了验证入口和reload入口。

@RequestMapping("/test") 
@Controller public class TestController { 
 
 @Resource private ReloadDroolsRules rules; 
 @ResponseBody @RequestMapping("/address") public void test(){ 
        KieSession kieSession = KieUtils.getKieSession(); 
 
        Address address = new Address(); 
        address.setPostcode("994251"); 
 
        AddressCheckResult result = new AddressCheckResult(); 
        kieSession.insert(address); 
        kieSession.insert(result); int ruleFiredCount = kieSession.fireAllRules(); 
        System.out.println("触发了" + ruleFiredCount + "条规则"); 
 if(result.isPostCodeResult()){ 
            System.out.println("规则校验通过"); 
        } 
 
    } 
 
 @ResponseBody @RequestMapping("/reload") public String reload() throws IOException { 
        rules.reload(); return "ok"; 
    } 
}

其他

其他类和文件内容参考springboot集成部分或demo源代码。

操作步骤如下:启动项目访问http://localhost:8080/test/address 会首先触发默认加载的address.drl中的规则。当调用reload之后,再次调用次方法会发现触发的规则已经变成重新加载的规则了。
GitHub demo下载地址:https://github.com/secbr/drools/tree/master/springboot-drools-reload-rules

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/15198.html

(0)
上一篇 2021年7月19日 17:34
下一篇 2021年7月19日 17:34

相关推荐

发表回复

登录后才能评论