【问题标题】:Library for evaluating logical expressions on Java objects用于评估 Java 对象上的逻辑表达式的库
【发布时间】:2012-10-02 13:38:53
【问题描述】:

假设我有以下课程:

class Person {
    int age;
    String city;
    Collection<Person> friends;
    Person spouse;
}

我需要一个库,它可以让我评估给定 Person 对象上的逻辑表达式是否为真。表达式看起来像这样:

((age>25 OR spouse.age>27) AND city=="New-York" AND size(friends)>100)

所以,要求是:

  1. 能够使用基本的逻辑运算符
  2. 访问给定对象的属性
  3. 访问内部对象的属性
  4. 使用简单的数学\类似 sql 的函数,例如 size、max、sum

建议?

【问题讨论】:

  • 您能说说为什么不能使用纯 Java 来执行此操作吗?表达式必须来自动态字符串吗?
  • 为什么不自己写函数??
  • 为什么你需要任何库??
  • 为什么你需要一个库来做任何事情?因为它比看起来更复杂(主要是解析问题),而且你可能会遇到很多陷阱,而可靠的库已经消除了这些陷阱。

标签: java expression evaluate


【解决方案1】:

您可以使用ScriptEngine + 反射:

  • 访问对象中的所有fields 并创建具有这些值的变量
  • 评估表达式

这是一个人为的例子,输出:

age = 35
city = "London"
age > 32 && city == "London" => true
age > 32 && city == "Paris" => false
age < 32 && city == "London" => false

如果你想处理非原始类型,比如集合,它可能会变得非常混乱。

public class Test1 {

    public static void main(String[] args) throws Exception{
        Person p = new Person();
        p.age = 35;
        p.city = "London";

        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("JavaScript");

        Class<Person> c = Person.class;
        for (Field f : c.getDeclaredFields()) {
            Object o = f.get(p);
            String assignement = null;
            if (o instanceof String) {
                assignement = f.getName() + " = \"" + String.valueOf(o) + "\"";
            } else {
                assignement = f.getName() + " = " + String.valueOf(o);
            }
            engine.eval(assignement);
            System.out.println(assignement);
        }

        String condition = "age > 32 && city == \"London\"";
        System.out.println(condition + " => " + engine.eval(condition));

        condition = "age > 32 && city == \"Paris\"";
        System.out.println(condition + " => " + engine.eval(condition));

        condition = "age < 32 && city == \"London\"";
        System.out.println(condition + " => " + engine.eval(condition));
    }

    public static class Person {

        int age;
        String city;
    }
}

【讨论】:

    【解决方案2】:

    好的,我想我找到了我想要的,这是 assylias 答案的变体,但我更喜欢它,因为它更标准化(不想专门依赖 Javascript 表达式,或者根本不想运行 Javascript)。

    显然有一个 Unified Expression Language 用于评估表达式,它最初是为 JSP 设计的,但也可以用于其他东西。有几种解析器实现,我可能会使用Spring ELJUEL

    【讨论】:

      猜你喜欢
      • 2012-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      相关资源
      最近更新 更多