Spring Boot中基于配置文件控制Drools规则执行范围的技术问询
Got it, here's a clean, maintainable way to implement your requirement—controlling which Drools rules run via a YAML config, with easy enable/disable just by commenting or removing entries:
1. Create a YAML Config for Enabled Rules
First, make a config file (can use any extension, e.g., rules-config.yml, rules.list, etc.) in your src/main/resources directory. List all rules you want to execute, and comment out or delete entries to disable them:
enabled-rules: - "user-validation-rule.drl" - "order-discount-rule.drl" # - "deprecated-customer-rule.drl" # Commented out = disabled - "shipping-cost-calculator.rule" # Works with non-.drl extensions too
2. Bind YAML Config to a Spring Bean
Create a configuration properties class to map the YAML entries into a usable list in your code. This lets Spring automatically load the config values:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.List; @Component @ConfigurationProperties(prefix = "") # Leave empty since our root key is `enabled-rules` public class RulesConfig { private List<String> enabledRules; // Getters and Setters public List<String> getEnabledRules() { return enabledRules; } public void setEnabledRules(List<String> enabledRules) { this.enabledRules = enabledRules; } }
Note: Don't forget to add @EnableConfigurationProperties(RulesConfig.class) to your main Spring Boot application class if you choose not to use @Component on the config class.
3. Custom Drools Rule Loader (Skip Auto-Scan)
Instead of letting Drools auto-load all rules in your classpath, we'll manually load only the rules listed in the YAML. Create a Drools configuration bean:
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.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import java.io.IOException; @Configuration public class DroolsConfig { private final RulesConfig rulesConfig; // Constructor injection for the rules config public DroolsConfig(RulesConfig rulesConfig) { this.rulesConfig = rulesConfig; } @Bean public KieContainer kieContainer() throws IOException { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); // Validate config has rules (optional but recommended) if (rulesConfig.getEnabledRules() == null || rulesConfig.getEnabledRules().isEmpty()) { throw new IllegalArgumentException("No enabled rules found in your config file!"); // Alternatively, load a default rule set here if needed } // Load each enabled rule file into Drools PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); for (String ruleFileName : rulesConfig.getEnabledRules()) { // Adjust the path below to match where your rules are stored Resource resource = resolver.getResource("classpath:rules/" + ruleFileName); kieFileSystem.write( resource.getFile().getAbsolutePath(), kieServices.getResources().newInputStreamResource(resource.getInputStream()) ); } // Build and return the KieContainer KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem); kieBuilder.buildAll(); KieModule kieModule = kieBuilder.getKieModule(); return kieServices.newKieContainer(kieModule.getReleaseId()); } }
Important: Update the classpath:rules/ path to match your actual rule file location (e.g., classpath: if rules are directly in resources).
4. Execute Rules in Your Business Logic
Inject the KieContainer into your service/controller and use it to create a session and run rules as usual:
import org.kie.api.runtime.KieSession; import org.springframework.stereotype.Service; @Service public class RuleExecutorService { private final KieContainer kieContainer; public RuleExecutorService(KieContainer kieContainer) { this.kieContainer = kieContainer; } public void runRules(Object businessFact) { KieSession kieSession = kieContainer.newKieSession(); try { kieSession.insert(businessFact); kieSession.fireAllRules(); } finally { kieSession.dispose(); // Always clean up the session } } }
Bonus: Optional Enhancements
- Hot Reload: If you want to update the YAML config without restarting the app, add a file watcher to reload the
RulesConfigand rebuild theKieContainerwhen changes are detected. - Rule Validation: Add checks to ensure each rule file exists before trying to load it, to avoid runtime errors.
- Default Rules: Fall back to a set of default rules if the
enabled-ruleslist is empty.
内容的提问来源于stack exchange,提问作者vinod chowdary

