简体   繁体   English

用于评估 Java 对象上的逻辑表达式的库

[英]Library for evaluating logical expressions on Java objects

Let's say I have the following class:假设我有以下课程:

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

I need a library which would allow me to evaluate whether a logical expression is true on a given Person object.我需要一个库,它可以让我评估给定 Person 对象上的逻辑表达式是否为真。 The expression would look something like this:表达式看起来像这样:

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

So, the requirements are:所以,要求是:

  1. Ability to use basic logical operators能够使用基本的逻辑运算符
  2. Access properties of the given object访问给定对象的属性
  3. Access properties of an internal object访问内部对象的属性
  4. Use simple mathematical\sql-like functions such as size,max,sum使用简单的数学\类似 sql 的函数,例如 size、max、sum

Suggestions?建议?

You could use a ScriptEngine + reflection:您可以使用ScriptEngine + 反射:

  • access all the fields in your object and create variable that have those values访问对象中的所有字段并创建具有这些值的变量
  • evaluate the expression评估表达式

Here is a contrived example which outputs:这是一个人为的例子,它输出:

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

It could become quite messy if you want to deal with non primitive types, such as collections.如果您想处理非原始类型(例如集合),它可能会变得非常混乱。

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;
    }
}

OK, think I found what I wanted, it's a variation on assylias' answer but I prefer it since it's more standardized (woudn't want to depend specifically on Javascript expressions, or run Javascript at all for that matter).好的,我想我找到了我想要的,这是 assylias 答案的变体,但我更喜欢它,因为它更标准化(不想专门依赖 Javascript 表达式,或者根本不想运行 Javascript)。

Apparently there is a Unified Expression Language for evaluating expressions, it was originally designed for JSP but can be used for other stuff as well.显然有一个统一的表达式语言来评估表达式,它最初是为 JSP 设计的,但也可以用于其他东西。 There are several parser implementations, I'll probably go either with Spring EL or JUEL有几种解析器实现,我可能会使用Spring ELJUEL

You can use rhino library from Mozilla .您可以使用Mozilla 的 rhino 库 https://github.com/mozilla/rhino https://github.com/mozilla/rhino

Example :例子 :

@Test
public void shouldCheckLogicalOperations(){
    Context cx = Context.enter();
    try {
        Scriptable scope = cx.initStandardObjects();
        ScriptableObject.putProperty(scope, "form_admin_checked", true);
        ScriptableObject.putProperty(scope, "form_limit_value", 50000);

        String script = "((form_admin_checked && form_limit_value<2000) || (form_admin_checked && !form_admin_checked) || form_admin_checked && form_limit_value==50000)";
        String expectedResponse = "true";

        Object result = cx.evaluateString(scope, script, "<cmd>", 1, null);

        Assert.assertEquals(expectedResponse, result.toString());

    } finally {
        // Exit from the context.
        Context.exit();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM