java - 如何在运行时构建 kmodule.xml 以更新 drl 文件中所做的更改

标签 java spring-boot drools kie

我是流口水的新手。我正面临流口水引擎的问题。我有一个可以从 Web 界面创建规则的用户,我使用一些代码将从这些规则中创建 drl 文件。到这里一切都按预期工作。现在,用户将通过向公开的 api 发送请求来提供输入,并根据一些参数值,我们将选择一个 drl 文件并执行规则。早些时候我在做什么,对于每个请求,我都在读取我生成到 kieFileSystem 中的 drl 文件并构建它。因此,如果用户发送 3 个参数,那么我将一个一个地构建 3 个不同的文件并执行它们,这很慢。(3 个参数大约需要 1 秒,并且参数没有限制,因此他也可以发送 10-12 个,这将非常慢。)

public <T> void getScore(T droolsInput, String filePath, String fileName) throws Exception {
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();
        FileInputStream fis = new FileInputStream(filePath);
        kfs.write(fileName, kieServices.getResources().newInputStreamResource(fis));
        KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
        if (kieBuilder.getResults().hasMessages(Level.ERROR)) {
            throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().toString());
        }
        KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.insert(droolsInput);
        kieSession.fireAllRules();
        kieSession.dispose();
        fis.close();
    }

这是我之前使用的代码。现在我开始了解 kmodule.xml,我如何在启动我的应用程序时构建 kbases 和 ksession,我的响应时间从 1 秒变为近 300 毫秒。但问题是我需要在 META-INF 文件夹中启动我的应用程序之前创建 kmodule.xml 文件,否则它无法工作。(我不知道我是否做错了什么)。因此,当用户使用 Web 界面更新规则时,我们再次构建 drl 文件,当他点击 api 时,我们希望根据新规则给他输出。我们不想重新启动应用程序来重新部署规则。他们可以是许多使用该服务的用户。所以任何人都可以帮我解决这个问题。基本上我想要的是保持规则更新并尽可能缩短响应时间。

这是我用来生成 kmodule.xml 的代码,它对我不起作用。

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

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

        kieRepository.addKieModule(new KieModule() {
            @Override
            public ReleaseId getReleaseId() {
                return kieRepository.getDefaultReleaseId();
            }
        });
        System.out.println("#############################################################################");
        System.out.println(getRuleFiles()[0].getURL());
        // System.out.println();
        KieModuleModel kieModuleModel = getKieServices().newKieModuleModel();
        // KieFileSystem kieFileSystem = kieFileSystem();
        for (Resource file : getRuleFiles()) {
            String fileNameWithoutExt = file.getFilename().split("\\.")[0];
            KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel(fileNameWithoutExt).setDefault(true)
                    .setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
                    .setEventProcessingMode(EventProcessingOption.STREAM);
            kieBaseModel1.newKieSessionModel("session_" + fileNameWithoutExt).setDefault(true)
                    .setType(KieSessionModel.KieSessionType.STATEFUL).setClockType(ClockTypeOption.get("realtime"));
            kieBaseModel1.addPackage("rules." + fileNameWithoutExt);
            FileInputStream fis = new FileInputStream(file.getFile());
            kieFileSystem.write("src/main/resources/rules/" + fileNameWithoutExt + "/" + file.getFilename(),
                    getKieServices().getResources().newInputStreamResource(fis));

        }
        System.out.println(kieModuleModel.toXML());
        kieFileSystem.writeKModuleXML(kieModuleModel.toXML());
        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        if (kieBuilder.getResults().hasMessages(Level.ERROR)) {
            throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().toString());
        }

        return getKieServices().newKieClasspathContainer("mycontainer");

    }

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

    @Bean
    public KieFileSystem kieFileSystem() throws IOException {
        return getKieServices().newKieFileSystem();

    }

这是我用来触发规则的代码。

@Autowired
    private KieContainer kieContainer;

    public <T> void getScore(T droolsInput, String filePath, String fileNameWithPath, String filename)
            throws Exception {
        KieSession kieSession = kieContainer.newKieSession("session_" + filename.split("\\.")[0]);
        kieSession.insert(droolsInput);
        kieSession.fireAllRules();
        kieSession.dispose();
    }

所以基本上如果 kmodule.xml 存在于项目的 META-INF 文件夹中,上面的 fireRules 代码就可以工作,否则它就不起作用。

最佳答案

应该可以单独编译每个 DRL 文件以获得 KiePackage,并将它们任意组合(根据参数)到生成 session 的 KieBase 中。但我认为这需要访问内部 API,该 API 如有更改,恕不另行通知。

因此我会使用另一种方法。

添加一个

class Parameters {
    Set<String> set = ...
}

和每个 X.drl 的一个规则:

rule selectX
when
    Parameters( set contains "X" ) # pattern to select X
then
end

并将所有规则写入X.drl

rule some_rule_in_X
extends selectX
    // ...

或者,将选择 X 的模式写入每个规则。

要激活,插入从发布请求派生的类参数的对象。

关于java - 如何在运行时构建 kmodule.xml 以更新 drl 文件中所做的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46399022/

相关文章:

java - Drools 集成到 Web 应用程序中

java - 如何通过jpql中的属性(name_techno)查找数据

java - 如何比较两个纳米时间值? [javadoc 困惑]

angular - docker容器中的前端和后端

java - Tomcat 上的 SpringBoot : Error creating bean with name 'jacksonObjectMapperBuilder'

java - 用于 Drools 的 Eclipse Java 自动完成

java - 使用比较器对对象进行排序给出空指针

java - 将 .csv 字符串值转换为 double

java - 如何使用 "java -cp example.jar com.example.MyMainClass"运行我的 Spring Boot 应用程序

对于 5.4.0 以上版本,Drools 规则检查集合中的空条件