Java-mvel表达式使用
使用原因
最近的项目中需要使用到mvel表达式做计算,遍对此进行了了解,在此将使用的经历分享给大家
引入mvel
在此我使用的时maven官方库的最新包,个人建议降2个版本使用,或使用使用人数最多的版本
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.4.8.Final</version>
</dependency>
初步测试
mvel表达式的使用很简单,详细使用参考官方文档,这里先写一个简单的测试代码
public static void main(String[] args){
//mvel表达式,功能:变量大于10,a加1,小于10则减1
String expression = "int a = 10;" +
"if(case1 < 10){System.out.println('less 10');a += 1;}" +
"else{System.out.println('more then 10'); a -= 1;} return a;";
//在这个map中放入使用到的变量
Map vars = new HashMap();
vars.put("case1", new Integer(12));
//运行表达式
Integer result = (Integer) MVEL.eval(expression, vars);
System.out.println("result: " + result);
}
mvel表达式中支持对象加‘.’的方式获取变量,如:可以将代码中的case1改为case.case1,同时在vars中放入名为case的对象,case对象中有case1字段。
添加mvel静态表达式
在使用的过程中,总会存在一些公共的方法,类似于java中的util,在resources文件夹中创建名为mvel的文件夹,并创建以mvel为后缀的文件(如mvel-function.mvel)(建议不要使用mvel.mvel这种文件名)
- 构建实际的表达式
private static String buildMvelExp(){
StringBuilder exp = new StringBuilder();
exp.append("int result = 0;");
// 使用表达式文件中的方法
exp.append("if(chgpaymode205(payIntv) < 10){");
exp.append("result = 10;");
exp.append("}else{");
exp.append("result = 20;");
exp.append("}");
exp.append("return result;");
return exp.toString();
}
- 引入相关文件
public static void main(String[] args) throws Exception{
String expression = buildMvelExp();
ParserContext ctx = new ParserContext();
VariableResolverFactory resolverFactory = new MapVariableResolverFactory();
// 这里使用的是springboot的文件路径
Resource resourcce = new ClassPathResource("mvel/mvel-function.mvel");
File scriptFile = resourcce.getFile();
MVEL.evalFile(scriptFile, ctx, resolverFactory);
// 添加使用到的变量
Map vars = new HashMap();
vars.put("payIntv", new Integer(15));
Integer result = (Integer) MVEL.eval(expression, vars, resolverFactory);
System.out.println("result: " + result);
}
以上关键在于resolverFactory,编译文件时需要带resolverFactory进行编译,同时运行表达式的使用需要带resolverFactory运行,原因在于编译文件的时候会把编译好的方法放入到resolverFactory中,所以使用的时候可以一次编译后,将resolverFactory作为缓存进行多次使用。
mvel支持添加多个方法文件,如
其中需要使用同一个resolverFactory。
在mvel静态文件中引入java的包
虽然mvel官方的jar中有ParserContext类,调用ParserContext.addImport()引入包,但是试了几次都没成功QAQ,所以这里只说我实验通过的。
- 在独立的mvel文件中直接引入
如图:
引入方法类似于java文件的的引入方法 - 在表达式中直接使用
这里复用上面构建mvel表达式的
private static String buildMvelExp(){
StringBuilder exp = new StringBuilder();
// 引入使用的java文件
exp.append("import java.text.SimpleDateFormat;");
exp.append("import java.util.*");
exp.append("result = '';");
// 使用表达式文件中的方法
exp.append("if(chgpaymode205(payIntv) < 10){");
exp.append("result = new SimpleDateFormat('yyyy-MM-dd').format(nowTime);");
exp.append("}else{");
exp.append("result = new SimpleDateFormat('yyyy-MM-dd').format(nowTime);");
exp.append("}");
exp.append("return result;");
return exp.toString();
}
这种用法可以引用已编译好的java方法,可以用于类似于热编译的场景,例如:可以先实时编译java代码,之后再表达式中调用编译好的java方法
目前就这样,之后再做更精细的操作教程,请谅解!!!