是否可以使用MVEL定义一些自定义的预编译函数并在另一个已编译表达式中使用它?
如果我尝试以下操作:
MVEL.compileExpression("function hello() { System.out.println(\"Hello!\"); hello(); return x * y;");
尝试第二次执行时,我得到
Exception in thread "main" [Error: duplicate function: hello]
。看来我不应该在表达式本身上声明函数,而应该在某种上下文中声明。我玩了ParsedContext一段时间,但总是得到
Exception in thread "main" [Error: unable to access property (null parent): hello]
。Internet上充满了涵盖不同MVEL语言用法主题的教程,但是此类嵌入主题的文献资料很少。您能给我一些提示我做错了什么吗?
附言我不想从Java执行某些功能。我需要使用MVEL动态定义它们。
最佳答案
尽管有可能,但是这比某些常见用例要复杂一些。
从根本上讲,您需要做的是创建一个定义函数的脚本,如下所示:
VariableResolverFactory functionFactory = new MapVariableResolverFactory();
MVEL.eval("def foo() { System.out.println("foo"); }; def bar() { System.out.println("bar") };", functionFactory);
然后,您要做的就是将此工厂反向链接到您运行的任何表达式:
VariableResolverFactory myVarFactory = new MapVariableResolverFactory();
myVarFactory.setNextFactory(functionFactory);
Serializable s = MVEL.compileExpression("foo(); bar();");
MVEL.executeExpression(s, myVarFactory);
函数记录为变量表上的引用,因此您可以使用常规变量工厂反向链接在MVEL中共享它们。
注意:您不应该重新共享“ myVarFactory”。您想每次创建一个新的。您只需要回收'functionFactory'并将其反向链接到如上所示的每次运行的工厂。否则,您最终将在执行之间共享本地var状态-这不是线程安全的