1、简介
在使用Drools规则引擎中,项目加载drools中的规则文件,需要保存在resources目录下才能被加载,如果使用自定义的路径存放drl文件,要实现动态加载该如何实现,本文将使用springboot框架集成Drools进行分享。
2、实现过程
2.1、pom.xml依赖
为了在springboot中使用Drools,需要引入下列依赖:
<!--drools规则引擎-->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>7.6.0.Final</version>
</dependency>
2.2、新建动态加载类
注意:这个地方需要配置正确规则文件资源路径
package com.test;
import lombok.extern.slf4j.Slf4j;
import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class DroolsDynamicService {
@Value("${drools.file.path}")
private String rulesPath;
public KieSession getKieSession() throws IOException {
KieContainer kieContainer = loadContainer();
return kieContainer.newKieSession();
}
private KieContainer loadContainer() throws IOException {
// 检查规则目录是否存在
Path rulesDir = Paths.get(rulesPath);
log.info("Loading rules from directory: {}", rulesDir.toAbsolutePath());
if (!Files.exists(rulesDir)) {
log.info("Rules directory does not exist, creating: {}", rulesDir.toAbsolutePath());
Files.createDirectories(rulesDir);
}
// 列出目录中的所有文件
log.info("Files in directory {}:", rulesDir.toAbsolutePath());
Files.list(rulesDir).forEach(path -> log.info("Found file: {}", path));
// 遍历规则目录下的所有.drl文件
List<Path> ruleFiles = Files.walk(rulesDir)
.filter(path -> path.toString().endsWith(".drl"))
.collect(Collectors.toList());
if (ruleFiles.isEmpty()) {
log.warn("No .drl files found in directory: {}", rulesDir.toAbsolutePath());
}
// 创建 KieFileSystem
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
for (Path path : ruleFiles) {
try {
log.info("Loading rule file: {}", path.toAbsolutePath());
File ruleFile = path.toFile();
if (ruleFile.exists() && ruleFile.isFile()) {
String content = new String(Files.readAllBytes(path));
// 使用正确的资源路径加载规则
String resourcePath = "src/main/resources/rules/" + ruleFile.getName();
log.info("Loading rule with resource path: {}", resourcePath);
kieFileSystem.write(resourcePath, content);
log.info("Successfully loaded rule file: {}", path.getFileName());
} else {
log.warn("Rule file does not exist or is not a file: {}", path.toAbsolutePath());
}
} catch (Exception e) {
log.error("Error loading rule file: " + path.toAbsolutePath(), e);
}
}
// 构建 KieModule
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
Results results = kieBuilder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
String errors = results.toString();
log.error("Build Errors:\n{}", errors);
throw new RuntimeException("Build Errors:\n" + errors);
}
// 创建 KieContainer
KieContainer container = kieServices.newKieContainer(kieBuilder.getKieModule().getReleaseId());
// 验证规则是否被加载
if (container.verify().hasMessages(Message.Level.ERROR)) {
String errors = container.verify().toString();
log.error("Container verification errors:\n{}", errors);
throw new RuntimeException("Container verification errors:\n" + errors);
}
// 打印加载的规则信息
log.info("Loaded rules in KieBase:");
container.getKieBase().getKiePackages().forEach(pkg -> {
log.info("Package: {}", pkg.getName());
pkg.getRules().forEach(rule -> {
log.info(" Rule: {}", rule.getName());
});
});
log.info("Successfully created KieContainer with {} rule files", ruleFiles.size());
return container;
}
}
2.3、配置文件(application.yml)
drools:
file:
path: D:\drools_file
2.4、使用
为了能保证动态加载,在使用的时候,每获取一次 KieSession 就加载一次drl文件就可以解决
@Service
public class Test{
@Autowired
private DroolsDynamicService droolsDynamicService;
public void test(){
KieSession kieSession = null;
try {
kieSession = droolsDynamicService.getKieSession();
} catch (IOException e) {
throw new RuntimeException("获取KieSession异常:" + e.getMessage());
}
User user = new User();
kieSession.insert(user);
kieSession.fireAllRules();
kieSession.dispose();
}
}
3、总结
Drools对于规则变化的场景,能够在不该写代码的情况下,通过配置规则配置文件,实现逻辑变动,对于Drools应用还有很多需要注意的地方,本文只是记录博主在开发过程中踩过的一个坑。

752

被折叠的 条评论
为什么被折叠?



