我对drools很陌生。我面临一个drools引擎的问题。我有一个可以从Web界面创建规则的用户,我使用一些代码将从这些规则中创建drl文件。到目前为止,一切都按预期工作。现在用户将通过post请求向暴露的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,如何在启动我的应用程序时构建kbase和ksession,我的响应时间从1秒到近300msec。但问题是我需要在启动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文件夹中,则上面的flur规则代码可以工作,否则它不起作用。
应该可以单独编译每个DRL文件以获得KiePackage,并将它们任意组合(根据参数)到生成会话的KieBase中。但我认为这需要访问内部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的模式写入每个规则。
要激活,请插入从post请求派生的Parameter类对象。