Java将字符串转换成可执行代码
commons-jexl3新版本
注意区分JexlScript和JexlExpression,
- JexlExpression可以支持多条语句,并返回最后一句执行结果。
- JexlExpression支持一条,返回当前条执行结果
- JexlExpression set = JEXL_ENGINE.createExpression(“pub.aString = value;pub.aString = value;”);
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-jexl3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl3</artifactId>
<version>3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
package com.example.demo1.test7;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.JexlScript;
import org.apache.commons.jexl3.MapContext;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author crwu
*/
public class Test2 {
private static final JexlEngine JEXL_ENGINE = new JexlBuilder().strict(true).silent(false).cache(32).create();
// some constants
private static final String LOWER42 = "fourty-two";
private static final String UPPER42 = "FOURTY-TWO";
/**
* An Inner class.
*/
public static class Inner {
public static double aDouble = 42.0;
public static double NOT42 = -42.0;
}
/**
* A Struct, all fields public
*/
public static class Struct {
public Inner inner = new Inner();
public int anInt = 42;
public String aString = LOWER42;
}
// a pub instance
private Struct pub;
// the JexlContext to use
private JexlContext ctxt;
@Before
public void setUp() {
pub = new Struct();
ctxt = new MapContext();
ctxt.set("pub", pub);
}
@Test
public void testGetInt() throws Exception {
JexlExpression get = JEXL_ENGINE.createExpression("pub.anInt");
Assert.assertEquals(42, get.evaluate(ctxt));
JEXL_ENGINE.setProperty(pub, "anInt", -42);
Assert.assertEquals(-42, get.evaluate(ctxt));
}
@Test
public void testSetInt() throws Exception {
JexlExpression set = JEXL_ENGINE.createExpression("pub.anInt = value");
ctxt.set("value", -42);
Assert.assertEquals(-42, set.evaluate(ctxt));
Assert.assertEquals(-42, JEXL_ENGINE.getProperty(pub, "anInt"));
ctxt.set("value", 42);
Assert.assertEquals(42, set.evaluate(ctxt));
Assert.assertEquals(42, JEXL_ENGINE.getProperty(pub, "anInt"));
try {
ctxt.set("value", UPPER42);
Assert.assertEquals(null, set.evaluate(ctxt));
Assert.fail("should have thrown");
} catch (JexlException xjexl) {
xjexl.printStackTrace();
}
}
@Test
public void testGetString() throws Exception {
JexlExpression get = JEXL_ENGINE.createExpression("pub.aString");
Assert.assertEquals(LOWER42, get.evaluate(ctxt));
JEXL_ENGINE.setProperty(pub, "aString", UPPER42);
Assert.assertEquals(UPPER42, get.evaluate(ctxt));
}
@Test
public void testSetString() throws Exception {
JexlExpression set = JEXL_ENGINE.createExpression("pub.aString = value;");
ctxt.set("value", UPPER42);
Assert.assertEquals(UPPER42, set.evaluate(ctxt));
Assert.assertEquals(UPPER42, JEXL_ENGINE.getProperty(pub, "aString"));
ctxt.set("value", LOWER42);
Assert.assertEquals(LOWER42, set.evaluate(ctxt));
Assert.assertEquals(LOWER42, JEXL_ENGINE.getProperty(pub, "aString"));
}
@Test
public void testGetInnerDouble() throws Exception {
JexlExpression get = JEXL_ENGINE.createExpression("pub.inner.aDouble");
Assert.assertEquals(42.0, get.evaluate(ctxt));
JEXL_ENGINE.setProperty(pub, "inner.aDouble", -42);
Assert.assertEquals(-42.0, get.evaluate(ctxt));
}
@Test
public void testSetInnerDouble() throws Exception {
JexlExpression set = JEXL_ENGINE.createExpression("pub.inner.aDouble = value");
ctxt.set("value", -42.0);
Assert.assertEquals(-42.0, set.evaluate(ctxt));
Assert.assertEquals(-42.0, JEXL_ENGINE.getProperty(pub, "inner.aDouble"));
ctxt.set("value", 42.0);
Assert.assertEquals(42.0, set.evaluate(ctxt));
Assert.assertEquals(42.0, JEXL_ENGINE.getProperty(pub, "inner.aDouble"));
try {
ctxt.set("value", UPPER42);
Assert.assertEquals(null, set.evaluate(ctxt));
Assert.fail("should have thrown");
} catch (JexlException xjexl) {
}
}
public enum Gender {MALE, FEMALE}
@Test
public void testGetEnum() throws Exception {
ctxt.set("gender", Gender.class);
String src = "x = gender.MALE;y = gender.FEMALE;";
JexlScript script = JEXL_ENGINE.createScript(src);
Object result = script.execute(ctxt);
// 返回最后一个语句的结果
System.out.println(result);
Assert.assertEquals(Gender.MALE, ctxt.get("x"));
Assert.assertEquals(Gender.FEMALE, ctxt.get("y"));
}
@Test
public void testGetStaticField() throws Exception {
ctxt.set("Inner", Inner.class);
String src = "x = Inner.NOT42;y = Inner.aDouble;";
JexlScript script = JEXL_ENGINE.createScript(src);
Object result = script.execute(ctxt);
// 返回最后一个语句的结果
System.out.println(result);
Assert.assertEquals(Inner.NOT42, ctxt.get("x"));
Assert.assertEquals(Inner.aDouble, ctxt.get("y"));
}
@Test
public void testWhile() throws Exception {
JexlContext jc = new MapContext();
jc.set("a", 1);
jc.set("b", "0");
jc.set("ans", new StringBuffer());
JexlScript e = JEXL_ENGINE.createScript("while (a < 10) {a = a + 1;ans.append(b);}");
e.execute(jc);
System.out.println(jc.get("ans"));
}
}
commons-jexl老版本
https://blog.csdn.net/weixin_38019299/article/details/85798768
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-jexl -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl</artifactId>
<version>2.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
package com.example.demo1.test7;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* @author crwu
*/
public class Test {
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
private String a;
private static JexlEngine jexlEngine = new JexlEngine();
public static void main(String[] args) {
// t1();
// t2();
// t3();
// t4();
// t5();
// t6();
t7();
}
public static void t7() {
Test tmpTest = new Test();
tmpTest.setA("1");
JexlContext jc = new MapContext();
jc.set("tmpTest", tmpTest);
jc.set("ans", "");
Expression e = jexlEngine.createExpression("ans = tmpTest.getA()");
e.evaluate(jc);
System.out.println(jc.get("ans"));
System.out.println("============================");
e = jexlEngine.createExpression("ans = tmpTest.setA(\"2\")");
e.evaluate(jc);
Test tmpTest1 = (Test) jc.get("tmpTest");
System.out.println(tmpTest1.getA());
}
public static void t6() {
JexlContext jc = new MapContext();
String str = "一二三四五六七八九十";
jc.set("Util", new Util());
jc.set("str", str);
jc.set("ans", "");
String expression = "ans = Util.regMatch(\"[\u4e00-\u9fa5]{10,}\",str)";
Expression e = new JexlEngine().createExpression(expression);
e.evaluate(jc);
System.out.println(jc.get("ans"));
}
private static void t5() {
JexlContext jc = new MapContext();
jc.set("a", 1);
jc.set("b", "0");
jc.set("ans", new StringBuffer());
Expression e = jexlEngine.createExpression("while (a < 10) {a = a + 1;ans.append(b);}");
e.evaluate(jc);
System.out.println(jc.get("ans"));
}
private static void t4() {
JexlContext context = new MapContext();//创建Context设值对象
String expressionStr = "array.size()";//表达式,表达式可以是数组的属性,元素等
List<Object> array = new ArrayList<Object>();//创建一个列表
array.add("this is an array");
array.add(new Integer(0));
context.set("array", array);//使用context对象将表达式中用到的值设置进去,必须是所有用到的值
Expression expression = jexlEngine.createExpression(expressionStr);//使用引擎创建表达式对象
Object o = expression.evaluate(context);//使用表达式对象开始计算
System.out.println(o);//输出:2
}
private static void t3() {
JexlContext jc = new MapContext();
jc.set("x", 10);
jc.set("y", 20);
Expression e = jexlEngine.createExpression("x - y");
Object result = e.evaluate(jc);
System.out.println(result);
}
private static void t2() {
Expression e = jexlEngine.createExpression("10 > 5 && \"test jexl\".contains(\"test\")");
Object result = e.evaluate(null);
System.out.println(result);
}
private static void t1() {
Map<String, Object> map = new HashMap<>();
map.put("alive", "coding every day");
map.put("err", System.err);
String expression = "err.print(alive)";
Test.executeExpression(expression, map);
}
public static Object executeExpression(String jexlExpression, Map<String, Object> map) {
Expression expression = jexlEngine.createExpression(jexlExpression);
JexlContext context = new MapContext();
if (MapUtils.isNotEmpty(map)) {
// map.forEach(context::set);
map.forEach((s, o) -> context.set(s, o));
}
return expression.evaluate(context);
}
static class Util {
public static boolean regMatch(String regEx, String str) {
Pattern pattern = Pattern.compile(regEx);
return pattern.matcher(str).matches();
}
}
}