簡體   English   中英

用於評估 Java 對象上的邏輯表達式的庫

[英]Library for evaluating logical expressions on Java objects

假設我有以下課程:

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

建議?

您可以使用ScriptEngine + 反射:

  • 訪問對象中的所有字段並創建具有這些值的變量
  • 評估表達式

這是一個人為的例子,它輸出:

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

好的,我想我找到了我想要的,這是 assylias 答案的變體,但我更喜歡它,因為它更標准化(不想專門依賴 Javascript 表達式,或者根本不想運行 Javascript)。

顯然有一個統一的表達式語言來評估表達式,它最初是為 JSP 設計的,但也可以用於其他東西。 有幾種解析器實現,我可能會使用Spring ELJUEL

您可以使用Mozilla 的 rhino 庫 https://github.com/mozilla/rhino

例子 :

@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