mvel的执行方式分为两种:一种解释执行和编译执行.解释模式是一个无状态的,动态解释执行。不像编译模式需要负载表达式,他不需要就可以执行相应的脚本。编译模式需要在缓存中产生一个完全规范化表达式之后再执行.表达式通常被称为speed-sensitive应用,第二个选项可能会更好。
Dependencies
要使用mvel只需要一个mvel.jar即可
The MVEL Convenience Class
为了使得使用简单和直接,mvel大部分的接口使用了静态方法,使得你在应用程序中可以直接使用
几乎所有的交互将围绕org.mvel2.MVEL类的使用。
Interpreted Mode
正如本节所介绍,解释模式是一种快速、动态parser-interpreterMVEL,所谓的快是,指的是相比一些其他的EL实现.
调用解释器主要集中在MVEL类中的eval()方法。
Integration Example: MVELTest.java
import org.mvel.MVEL; public class MVELTest { public static void main(String[]args) { String expression ="foobar > 99"; Map vars = new HashMap(); vars.put("foobar",new Integer(100)); // We know this expressionshould return a boolean. Boolean result = (Boolean)MVEL.eval(expression, vars); if (result.booleanValue()) { System.out.println("Itworks!"); } } }
Compiled Mode
编译和执行一个表达式,需要做的不是简单地调用一个方法。它包括两种方法!
Integration Example: MVELTest2.java
import org.mvel.MVEL;
public class MVELTest2 {
public static void main(String[]args) {
String expression ="foobar > 99";
// Compile the expression.
Serializable compiled =MVEL.compileExpression(expression);
Map vars = new HashMap();
vars.put("foobar",new Integer(100));
// Now we execute it.
Boolean result = (Boolean)MVEL.executeExpression(compiled, vars);
if (result.booleanValue()) {
System.out.println("Itworks!");
}
}
}
在MVEL2.0,您可以将编译器设置为强类型模式,这样类型转换会在脚本内部进行转换.这意味着必须告知编译器注入任何类型的变量。这也意味编译器可以在编译时告知返回类型。
Turning on StrongTyping
调用ParserContext的启动接口:setStrongTyping
// create new parser context
ParserContext ctx = newParserContext();
// turn on strong typing
ctx.setStrongTyping(true);
//compile an expression'str.toUpperCase()'
String expression ="str.toUpperCase()";
CompiledExpression ce =MVEL.compileExpression(expression, ctx);
运行上面的代码会报错
[Error: Failed to compile: 2 compilation error(s):
- (1,3) unqualified type in strict mode for: str
- (1,17) unable to resolve method using strict-mode: java.lang.Object.toUpperCase(...)]
这是因为我们没有设置强制转换的类型,
// create new parser context
ParserContext ctx = new ParserContext();
// turn on strong typing
ctx.setStrongTyping(true);
// declare the type of 'str'
ctx.addInput("str", String.class);
//compile an expression 'str.toUpperCase()'
String expression = "str.toUpperCase()";
CompiledExpression ce = MVEL.compileExpression(expression, ctx);
我们还可以通过CompiledExpression 对象的getEgressType()方法来确定返回的对象类型:
Class returnType = ce.getKnownEgressType(); // returns java.lang.String in this case.
MVEL还可以指定生产类型的类型参数,比如:
ParserContext ctx = new ParserContext();
ctx.setStrongTyping(true);
// Specify the type of "foo" and it's type parameters.
ctx.addInput("foo", HashMap.class, new Class[]{String.class, String.class});
String expression = "foo.get('bar').toUpperCase()";
Serializable ce = MVEL.compileExpression(expression, ctx);
在这种情况下,该表达式可以编译成功并执行,因为MVEL能够确定foo.get的返回类型根据输入的时候被指定的类型参数。
1. Optimizers
优化器通常只使用于编译模式,而不考虑在eval解释模式下.
由于MVEL是动态运行时的动态语言,所以需要通过反射的对象让脚本访问字段和方法。但这严重影响性能,MVEL配备优化,为了最大限度地减少或消除反射调用的开销。默认情况下,MVEL有两个默认优化:反射优化器,ASM字节码优化器。
反射优化器
反射优化器在一些api中也被称为SAFE_REFLECTIVE优化器,表示他是绝对安全的,不会对类加载造成影响,保证兼容所有的语言结构.ASM优化器可能会在某些情况下,由于各种原因不能被编译成字节码,对于某些操作会依靠这个优化器。
优化器的配置可以通过MVELsOptimizerFactory进行配置:
OptimizerFactory.setDefaultOptimizer("reflective");
The ASM (Bytecode) Optimizer
ASM字节码优化器在MVEL是默认启用。它使用一个内联版本的ASM3.0字节码操作库产生编译反射访问器存根用于反射调用的地方。优化器是由默认使用API调用如下:
OptimizerFactory.setDefaultOptimizer("ASM");
2. Programmatic Imports for 2.0
默认情况下,如java中,mvel自动将所有java.lang.* 预加载到了运行执行环境中去.同时,MVEL能够以编程方式导入单个类,整个包,甚至是静态方法.
这样看来好像有点偏离了MEVL这个类,但是这个没有太大关系.
Importing Classes
看下面代码:
// where someExpression is a String or char[] of the expression to be compiled.
ParserContext context = new ParserContext();
context.addImport("Message", Message.class);
context.addImport("MessageFactory", MessageFactory.class);
Serializable compiled = MVEL.compileExpression(someExpression, context); // compile the expresion
上面的例子中我们为运行时添加了两个自定义的类型,他们都使用了原来的名称,但事实上你可以修改成任意合法的名称.比如:
context.addImport("Utils", ScriptUtilities.class);
Importing Packages
导入包:
ParserContext ctx = new ParserContext();
ctx.addPackageImport("java.util"); // imports the entire java.util.* package.
Serializable s = MVEL.compileExpression("map = new HashMap();", ctx);
Importing Static Methods
ParserContext ctx = new ParserContext();
try {
ctx.addImport("time", System.class.getMethod("currentTimeMillis"));
}
catch (NoSuchMethodException e) {
// handle exception here.
}
Serializable s = MVEL.compileExpression("time();" ctx);
3. 自定义变量解析器
略
4. 自定义属性处理程序
略...见java doc文档
5. 类型转换
略..
6. 行调试器接口