【问题标题】:Putting a simple expression language into java将简单的表达式语言放入java
【发布时间】:2011-06-08 20:46:31
【问题描述】:

作为我的 Java 应用程序,用户可以从一系列元数据字段中指定如何命名他们的文件。即

%artist% - %album% - %disctotal%

然后我的代码会解析这些字段并相应地重命名文件。但我希望用户能够使用“表达语言”,这样他们就可以说:

$if(%disctotal% >= 01,%discno%) 

使用ifelse,比较长度和大小写等。

我不想从头开始写这个,有什么东西可以为我提供这个我可以插入到我的代码中的东西吗?

编辑:我认为我有一些很好的回复,但我的知识让我失望了。让我们简化我希望用户能够编写的问题

$if(%disctotal% >= 01,%discno%)

进入 gui 中的字段。

然后稍后在我的 Java 代码中,我希望能够将此表达式应用于一组文件,因此对于每个文件,我都有 disctotal 和 discno 的值,但我希望能够将表达式转换为某些东西喜欢

如果(光盘总数 >=1) { 返回盘无 } 别的 { 返回 ”” }

我不想做的是必须编写识别字符串的代码(“ $if(%disctotal% >= 01,%discno%)" 是一个 if 语句,因为这样做很尴尬。

然后对此进行扩展,我希望表达式允许诸如大写 oof 字段、检查字段长度等内容。

或者:也许它应该以这种方式工作,用户输入表达式,然后在以后的每个文件中,Java 代码将每个变量替换为实际值

即 $if(%disctotal% >= 01,%discno%) -> $if(2 >= 01,1)

然后将this传给表达式语言解析并给出结果,

这是 Javascript 的想法吗?

【问题讨论】:

    标签: java expression


    【解决方案1】:

    使用JavaScript engine that is bundled with Java 1.6怎么样?

    您可以看到如何传入所有参数:

    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");
    engine.put("artist", artist);
    ...
    

    您可以使用

    读回该值
    ScriptEngine.get(...)
    

    最后一点粘合是用函数声明包围用户的表达式,并编写一个调用函数并将结果分配给众所周知的变量的表达式。

    所以要开始实验,让我们有一个函数来测试表达式:

    private static void printResult(final ScriptEngine jsEngine, String name, String expr) throws ScriptException {
        Object result = jsEngine.eval(expr);
        System.out.println(name + " result: " + result + "; expr: " + expr);
    }
    

    现在我们称之为:

    public static void main(String[] args) throws Exception {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine jsEngine = sem.getEngineByName("JavaScript");
        printResult(jsEngine, "Hello World", "'Hello World'");
        printResult(jsEngine, "Simple Math", "123 + 456");
    }
    

    这会产生:

    Hello World result: Hello World; expr: 'Hello World'
    Simple Math result: 579.0; expr: 123 + 456
    

    现在让我们试试你的用例:

    public static void main(String[] args) throws Exception {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine jsEngine = sem.getEngineByName("JavaScript");
    
        String expr = "artist + '-' + album + (disktotal > 1 ? ('-D' + diskno) : '')";
    
        jsEngine.put("artist", "U2");
        jsEngine.put("album", "The Joshua Tree");
        jsEngine.put("disktotal", 1);
        jsEngine.put("diskno", 1);
        printResult(jsEngine, "Single Disk", expr);
    
        jsEngine.put("artist", "Tori Amos");
        jsEngine.put("album", "To Venus and Back");
        jsEngine.put("disktotal", 2);
        jsEngine.put("diskno", 2);
        printResult(jsEngine, "Muti-Disk", expr);
    }
    

    产生结果:

    Single Disk result: U2-The Joshua Tree; expr: ...
    Muti-Disk result: Tori Amos-To Venus and Back-D2; expr: ...
    

    请注意 Tori's 的结尾是“D2”。

    【讨论】:

    • 这可能是正确的解决方案,但我不知道我正在努力解决这个问题。
    • 好的,我会在回答中提供更多细节
    【解决方案2】:

    我会调查FreeMarker。它是一个模板引擎。您可以将带有 el 构造的字符串传递给 Freemarker,并将您想要绑定到字符串的对象提供给它,它会返回一个字符串。

    【讨论】:

    • 也许吧,但我不想从 Java 输出一些东西,我想走另一条路,用户输入一个转换为 java 的表达式(我认为)
    【解决方案3】:

    一种选择是使用解析器生成器。

    ANTLR 就是这样一种 Java 工具。如果您是创建语法的新手,您会发现语法 IDE ANTLRWorks 很有用。

    【讨论】:

    • 可能是,这取决于您对语法的熟悉程度。是否值得部分取决于您要支持的语法的复杂性。
    【解决方案4】:

    我猜你正在寻找template engine

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-10
      • 2011-04-12
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多