如何在Drools模板中正确传递List和Map参数动态生成规则?
问题根源分析
你遇到的问题本质是:当用tag[]形式引用List/Map类型的对象时,ObjectDataCompiler会直接调用该对象的toString()方法输出内容,而Java中List的默认toString()会用[]包裹元素,Map会用{}包裹键值对,导致生成的DRL不符合规则语法要求。
正确实现示例
1. 定义Java实体类
假设你转换后的Java对象包含List和Map属性,示例类如下:
public class RuleData { private List<String> whiteList; private Map<String, Integer> scoreMap; private String ruleName; // 省略getter、setter、构造方法 }
2. 编写正确的Drools模板(.drlftl)
针对List和Map,需要遍历元素或按key取值,而不是直接引用整个集合对象:
package com.example.rules; rule "${ruleName}" when // 处理List:用Freemarker指令转成DRL兼容的元素列表 $user: User(name in (${#whiteList?join(", ", "'${.}'")})) // 处理Map:直接按key取对应值 $order: Order(totalAmount > ${scoreMap['threshold']}) then System.out.println("Rule triggered: ${ruleName}"); end
- 对于List:用Freemarker的
?join指令将元素转为带单引号的字符串列表,直接嵌入DRL的in条件中 - 对于Map:通过key直接取值,模板会输出对应的值,而非Map的toString结果
3. 使用ObjectDataCompiler编译生成DRL
import org.drools.template.ObjectDataCompiler; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class RuleGenerator { public static void main(String[] args) throws Exception { // 模拟JSON转成的Java对象 RuleData ruleData = new RuleData(); ruleData.setRuleName("UserWhiteListAndOrderThreshold"); List<String> whiteList = new ArrayList<>(); whiteList.add("Alice"); whiteList.add("Bob"); ruleData.setWhiteList(whiteList); Map<String, Integer> scoreMap = new HashMap<>(); scoreMap.put("threshold", 1000); ruleData.setScoreMap(scoreMap); // 加载模板文件 InputStream templateStream = RuleGenerator.class.getResourceAsStream("/rule-template.drlftl"); ObjectDataCompiler compiler = new ObjectDataCompiler(); // 编译生成DRL String drl = compiler.compile(new Object[]{ruleData}, templateStream); System.out.println(drl); } }
4. 生成的正确DRL示例
package com.example.rules; rule "UserWhiteListAndOrderThreshold" when $user: User(name in ('Alice', 'Bob')) $order: Order(totalAmount > 1000) then System.out.println("Rule triggered: UserWhiteListAndOrderThreshold"); end
额外说明
- 如果是嵌套集合(比如List
或Map<String, List>),可以用Freemarker的 <#list>循环指令遍历生成复杂条件 - 核心原则:永远不要直接输出集合对象本身,必须针对集合的元素或键值对做针对性处理
内容的提问来源于stack exchange,提问作者Harsha
相关产品推荐
相关产品推荐

