You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Easy-Rules规则引擎多事实触发问题及Shop Tutorial扩展咨询

解决Easy-Rules中遍历多个事实进行规则评估的问题

我之前在扩展Easy-Rules的规则时也遇到过类似的需求——要一次性处理多个事实并完成规则评估,而不是仅针对单个实例。这里有两个实用的方案,你可以根据自己的场景选择:

方案1:将多个事实包装为集合类事实(推荐用于声明式规则)

如果习惯用表达式(比如你提到的condition: "people.isAdult() == false"这种写法),最直接的方式是把多个同类型的事实包装成一个集合对象,作为单个事实存入Facts容器,然后在规则条件和动作中通过这个集合对象遍历所有实例。

步骤示例:

  1. 定义集合包装类
    先创建一个包含事实集合的类,封装遍历、过滤等逻辑,让规则表达式更简洁:

    import java.util.List;
    import java.util.stream.Collectors;
    
    public class PersonGroup {
        private List<Person> people;
    
        public PersonGroup(List<Person> people) {
            this.people = people;
        }
    
        // 判断集合中是否存在未成年人
        public boolean hasMinors() {
            return people.stream().anyMatch(person -> !person.isAdult());
        }
    
        // 获取所有未成年人
        public List<Person> getMinors() {
            return people.stream()
                    .filter(person -> !person.isAdult())
                    .collect(Collectors.toList());
        }
    
        // getter
        public List<Person> getPeople() {
            return people;
        }
    }
    
  2. 编写规则(表达式方式)
    现在可以在规则的when和then中直接调用包装类的方法,实现多事实的遍历评估:

    import org.jeasy.rules.api.Rule;
    import org.jeasy.rules.core.RuleBuilder;
    
    Rule minorAlertRule = new RuleBuilder()
            .name("未成年人提醒规则")
            .description("检测并处理人群中的未成年人")
            .when("personGroup.hasMinors()") // 条件:集合中存在未成年人
            .then("personGroup.getMinors().forEach(p -> System.out.println(p.getName() + \" 是未成年人,需要特殊处理\"))") // 动作:遍历处理所有符合条件的事实
            .build();
    
  3. 执行规则
    将包装好的集合事实传入Facts,触发规则:

    import org.jeasy.rules.api.Facts;
    import org.jeasy.rules.api.Rules;
    import org.jeasy.rules.core.DefaultRulesEngine;
    
    public class Main {
        public static void main(String[] args) {
            // 创建多个Person事实
            Person alice = new Person("Alice", 17);
            Person bob = new Person("Bob", 20);
            Person charlie = new Person("Charlie", 16);
    
            // 包装成集合事实
            PersonGroup group = new PersonGroup(List.of(alice, bob, charlie));
    
            Facts facts = new Facts();
            facts.put("personGroup", group);
    
            Rules rules = new Rules();
            rules.register(minorAlertRule);
    
            DefaultRulesEngine engine = new DefaultRulesEngine();
            engine.fire(rules, facts);
        }
    }
    

方案2:自定义规则直接操作Facts容器(适合灵活逻辑)

如果需要更灵活的控制(比如动态获取不同类型的事实,或者复杂的遍历逻辑),可以自定义规则类,重写evaluate和execute方法,直接从Facts容器中取出所有事实进行遍历。

步骤示例:

  1. 自定义规则类

    import org.jeasy.rules.api.Facts;
    import org.jeasy.rules.core.BasicRule;
    
    public class MinorCheckRule extends BasicRule {
    
        public MinorCheckRule() {
            super("未成年人检测规则", "遍历所有Person事实,处理未成年人");
        }
    
        @Override
        public boolean evaluate(Facts facts) {
            // 遍历Facts中所有Person类型的事实,判断是否存在未成年人
            return facts.values().stream()
                    .filter(Person.class::isInstance)
                    .map(Person.class::cast)
                    .anyMatch(person -> !person.isAdult());
        }
    
        @Override
        public void execute(Facts facts) throws Exception {
            // 遍历并处理所有符合条件的Person事实
            facts.values().stream()
                    .filter(Person.class::isInstance)
                    .map(Person.class::cast)
                    .filter(person -> !person.isAdult())
                    .forEach(person -> System.out.println("处理未成年人:" + person.getName()));
        }
    }
    
  2. 执行规则
    直接将多个Person事实存入Facts,注册自定义规则并触发:

    import org.jeasy.rules.api.Facts;
    import org.jeasy.rules.api.Rules;
    import org.jeasy.rules.core.DefaultRulesEngine;
    
    public class Main {
        public static void main(String[] args) {
            Facts facts = new Facts();
            facts.put("alice", new Person("Alice", 17));
            facts.put("bob", new Person("Bob", 20));
            facts.put("charlie", new Person("Charlie", 16));
    
            Rules rules = new Rules();
            rules.register(new MinorCheckRule());
    
            DefaultRulesEngine engine = new DefaultRulesEngine();
            engine.fire(rules, facts);
        }
    }
    

方案对比

  • 方案1:更符合Easy-Rules的声明式风格,规则逻辑清晰,适合用表达式或配置文件(YAML/JSON)定义规则的场景。
  • 方案2:灵活性更高,适合需要动态处理不同类型事实、或者逻辑复杂无法用简单表达式实现的场景,但需要编写Java代码实现规则逻辑。

内容的提问来源于stack exchange,提问作者E.Bülbül

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:47:05