《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之后,再次调用次方法会发现触发的规则已经变成重新加载的规则了。

CSDN demo下载地址:http://download.csdn.net/detail/wo541075754/9918297 GitHub demo下载地址:https://github.com/secbr/drools/tree/master/springboot-drools-reload-rules

后语

此系列课程持续更新中,QQ群:593177274,欢迎大家加入讨论。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏陈满iOS

iOS开发·网络请求方法总结复习(NSURLConnection,NSURLSession,AFNetworking)

iOS的开发中的网络下载方式包括NSData(最原始,实际开发基本不会用),NSURLConnection(古老又过气的苹果原生网络框架),NSURLSessi...

823
来自专栏hbbliyong

WPF备忘录(2)WPF获取和设置鼠标位置与progressbar的使用方法

一、WPF 中获取和设置鼠标位置   方法一:WPF方法 Point p = Mouse.GetPosition(e.Source as Framewo...

3317
来自专栏Hadoop实操

如何开发HBase Endpoint类型的Coprocessor以及部署使用

982
来自专栏jeremy的技术点滴

开发小技巧备忘

3167
来自专栏coolblog.xyz技术专栏

MyBatis 源码分析 - 插件机制

一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见的,一是增加了框架的灵活性。二是开发者可以结合实际需求,对框架进行拓展...

713
来自专栏coding

hexo搭建个人博客

搭建个人博客有很多种方式,最老牌的当属wordpress,功能丰富,但过于笨重。我想要的只是最简单的显示文章以及搜索功能,当然,样式要简洁漂亮,而且必须支持ma...

1027
来自专栏高性能服务器开发

+从零实现一款12306刷票软件1.4

这里还有个注意细节,就是通过POST请求发送的数据需要对一些符号做URL Encode,这个我在上一篇文章《从零实现一个http服务器》也详细做了介绍,还不清楚...

1312
来自专栏二进制文集

Java 知乎爬虫

基于 Java 的 webmagic,开发极其简单,这个知乎爬虫的代码主体就几行,而且只要专注提取数据就行了(其实是因为我也不知道其它 Java 的爬虫框架)。

904
来自专栏菩提树下的杨过

Silverlight的自定义tooltip提示工具条

这种应用场景其实很多,比如游戏中装备/魔法的选择菜单,这里借用了"深蓝色右手"的一张图  再比如聊天室中的文本颜色设置  ? 虽然sl的ToolTipServ...

2066
来自专栏数据之美

修改 mysql/oracle/bash/vimrc/cmd 提示符格式与颜色

(1)修改mysql提示符: MySQL 客户端的默认提示符是 "mysql>",基本上没什么实际作用。其实可以修改这个提示符,让它显示一些有用的信息,例如当前...

20010

扫码关注云+社区