在于Springboot集成的章节,我们介绍了怎样将Drools与Springboot进行集成,本章将介绍集成之后,如何实现从数据库读取规则并重新加载规则的简单demo。因本章重点介绍的是Drools相关操作的API,所以将查询数据库部分的操作省略,直接使用数据库查询出的规则代码来进行规则的重新加载。另外,此示例采用访问一个http请求来进行重新加载,根据实际需要可考虑定时任务进行加载等扩展方式。最终的使用还是要结合具体业务场景来进行分析扩展。详细代码参考github:https://github.com/secbr/drools

整体项目结构图
drools规则引擎基于Springboot动态加载规则实例插图

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

CSDN demo下载地址:http://download.csdn.net/detail/wo541075754/9918297

相关技术视频

QQ技术交流2群:715840230

CSDN学院:《Drools7规则引擎进阶教程》

CSDN学院:《Drools7规则引擎入门教程》

CSDN学院:《Drools7系列优惠套餐》

获得完整的《从Drools规则引擎到风控反洗钱系统》可评论留下邮箱。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注