Spring Boot集成Drools 8.33.0.Final无法读取Excel规则文件求助
解决Drools无法加载Excel/CSV规则文件的问题
环境信息
- Spring Boot:2.7.7
- Drools:8.33.0.Final
- Java:17
问题现象
开发Spring Boot RESTful服务时,使用Drools加载.xlsx/.xls/.csv格式的规则文件无效,控制台抛出警告:
No files found for KieBase defaultKieBase
测试请求URL:localhost:8080/getInterestRate?loanType=Fixed&age=45&durationInYear=1
相关代码
POM.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.7</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.codeusingjava</groupId> <artifactId>boot-drools</artifactId> <version>0.0.1-SNAPSHOT</version> <name>boot-drools</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</java.version> <drools.version>8.33.0.Final</drools.version> <!-- <drools.version>8.15.0.Beta</drools.version> --> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>${drools.version}</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-mvel</artifactId> <version>${drools.version}</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-decisiontables</artifactId> <version>${drools.version}</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>${drools.version}</version> </dependency> <dependency> <groupId>org.kie</groupId> <artifactId>kie-ci</artifactId> <version>${drools.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Drools配置类
import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.KieModule; import org.kie.api.runtime.KieContainer; import org.kie.internal.io.ResourceFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class DroolsConfiguration { private final KieServices kieServices = KieServices.Factory.get(); @Bean public KieContainer kieContainer() { KieContainer kieCont = null; try { KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); kieFileSystem.write(ResourceFactory.newClassPathResource("rules/discount.xlsx")); KieBuilder kb = kieServices.newKieBuilder(kieFileSystem); kb.buildAll(); KieModule kieModule = kb.getKieModule(); kieCont = kieServices.newKieContainer(kieModule.getReleaseId()); }catch(Exception exception) { exception.printStackTrace(); } return kieCont; } }
DepositRateController.java
package com.codeusingjava.bootdrools.controller; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.codeusingjava.bootdrools.model.DepositRequest; @RestController public class DepositRateController { @Autowired private KieContainer kieContainer; @RequestMapping(value = "/getInterestRate", method = RequestMethod.GET, produces = "application/json") public String getInterest(@RequestParam(required = true) String loanType, @RequestParam(required = true) Integer durationInYear, @RequestParam(required = true) Integer age) { KieSession kieSession = kieContainer.newKieSession(); DepositRequest depositRequest = new DepositRequest(loanType, durationInYear, age); kieSession.insert(depositRequest); kieSession.fireAllRules(); kieSession.dispose(); return "The interest rate for this application is " + depositRequest.getInterestRate(); } }
DepositRequest.java
package com.codeusingjava.bootdrools.model; public class DepositRequest { private String loanType; private Integer durationInYear; private Integer age; private String interestRate; public DepositRequest(String loanType, Integer durationInYear, Integer age) { super(); this.loanType = loanType; this.durationInYear = durationInYear; this.age = age; } public String getLoanType() { return loanType; } public void setLoanType(String loanType) { this.loanType = loanType; } public Integer getDurationInYear() { return durationInYear; } public void setDurationInYear(Integer durationInYear) { this.durationInYear = durationInYear; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getInterestRate() { return interestRate; } public void setInterestRate(String interestRate) { this.interestRate = interestRate; } }
控制台日志
Tomcat initialized with port(s): 8080 (http) 2023-02-17 13:20:01.551 INFO 19264 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-02-17 13:20:01.551 INFO 19264 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.70] 2023-02-17 13:20:01.955 INFO 19264 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2023-02-17 13:20:01.955 INFO 19264 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1006 ms 2023-02-17 13:20:02.891 WARN 19264 --- [ restartedMain] o.d.c.kie.builder.impl.KieProject : No files found for KieBase defaultKieBase 2023-02-17 13:20:03.073 INFO 19264 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2023-02-17 13:20:03.099 INFO 19264 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2023-02-17 13:20:03.105 INFO 19264 --- [ restartedMain] c.c.bootdrools.BootDroolsApplication : Started BootDroolsApplication in 2.433 seconds (JVM running for 3.26)
解决步骤
1. 验证规则文件路径与格式
- 确认
discount.xlsx文件位于src/main/resources/rules/目录,路径大小写与代码中一致(Linux/macOS环境需注意大小写敏感)。 - 确保Excel决策表符合Drools规范:包含
RuleSet、RuleName、CONDITION、ACTION等必填表头,规则逻辑单元格格式正确。
2. 明确指定资源类型加载Excel文件
Drools 8.x需要显式声明决策表资源类型,修改配置类中的资源加载代码:
import org.kie.api.io.ResourceType; @Configuration public class DroolsConfiguration { private final KieServices kieServices = KieServices.Factory.get(); @Bean public KieContainer kieContainer() { KieContainer kieCont = null; try { KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); // 显式设置资源类型为决策表 Resource resource = ResourceFactory.newClassPathResource("rules/discount.xlsx"); resource.setResourceType(ResourceType.DTABLE); kieFileSystem.write(resource); KieBuilder kb = kieServices.newKieBuilder(kieFileSystem); kb.buildAll(); KieModule kieModule = kb.getKieModule(); kieCont = kieServices.newKieContainer(kieModule.getReleaseId()); }catch(Exception exception) { exception.printStackTrace(); } return kieCont; } }
3. 添加kmodule.xml配置文件
在src/main/resources/META-INF/下创建kmodule.xml,定义KieBase和KieSession,让Drools正确识别规则目录:
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://www.drools.org/xsd/kmodule"> <kbase name="defaultKieBase" packages="rules"> <ksession name="defaultKieSession"/> </kbase> </kmodule>
其中packages="rules"对应resources/rules/目录,Drools会自动扫描该目录下的所有规则文件(包括决策表)。
4. 调试资源加载状态
在配置类中添加检查语句,确认资源是否存在:
Resource resource = ResourceFactory.newClassPathResource("rules/discount.xlsx"); System.out.println("规则文件是否存在:" + resource.exists());
若输出false,需调整文件路径或文件存放位置。
5. 清理并重新构建项目
执行Maven命令清理缓存并重新构建:
mvn clean install
内容的提问来源于stack exchange,提问作者Suresh Kumar
相关产品推荐
相关产品推荐

