碰到一个这样的需求,我们需要通过客户端上传的字符串来进行一个表达式的运算。下面我们来看看怎么实现这一个问题:
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>test2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.noear</groupId>
<artifactId>liquor</artifactId>
<version>1.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mvel/mvel2 -->
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.5.1.Final</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
测试代码:
package org.example;
import org.mvel2.MVEL;
import org.noear.liquor.DynamicCompiler;
import java.lang.reflect.Method;
import java.util.Map;
public class Main {
public static void main(String[] args) throws Exception{
System.out.println(getExpressValueByMvel("20<10||20<=40"));
}
public static boolean getExpressValueByMvel(String str) throws Exception {
return (boolean)MVEL.eval(str);
}
public static boolean getExpressValue(String str) throws Exception {
String className = "com.demo.proxy.MyClass";
String classCode = "package com.demo.proxy;\n" +
"\n" +
"public class MyClass {\n" +
"\n" +
" public boolean bool(){\n" +
" return "+str+";" +
" }\n" +
"}";
DynamicCompiler compiler = new DynamicCompiler();
compiler.addSource(className, classCode);
Map<String, Class<?>> classMap = compiler.build();
Class<?> aClass = classMap.get(className);
Method method= aClass.getMethod("bool");
return (boolean)method.invoke(aClass.newInstance());
}
}
getExpressValue用的是动态编译的一种方式,但是显而易见,太麻烦了,而且性能也不强(具体我也没测试过)
getExpressValueByMvel用的是规则引擎的一种方式。从上面的代码来看我们能够发现非常的简单。
参考文章: