首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取JEXL中的表达式值

获取JEXL中的表达式值
EN

Stack Overflow用户
提问于 2018-12-12 00:44:18
回答 2查看 3.2K关注 0票数 0

具有以下JEXL表达式:

代码语言:javascript
复制
String expression = "myVar >= 12345 && mySecondVar <= 56789";

我可以调用createScript和getVariables来获取myVar和mySecondVar作为值,例如:

代码语言:javascript
复制
Set<List<String>> expressionVars = JEXL.createScript(expression).getVariables();

我想知道的是,如果给定相同的表达式,我可以调用其他方法来返回这些变量的值。原因是我想验证其中一些值的输入。我查看了文档并尝试了JexlScript类,但找不到一种优雅的方法。因为JEXL已经在解析我的表达式了,所以如果能够检索这些信息,而不必手动解析我的表达式来获得这些值,那就太棒了。

返回12345script.getValue("myVar");中的一些内容

EN

回答 2

Stack Overflow用户

发布于 2018-12-20 17:56:04

使用JEXL,您可以在包含变量及其值的给定上下文(JexlContext)中计算脚本/表达式。JexlContext公开了“has”和“get”方法,这两个方法分别检查变量的存在和获取变量的值。在本例中,您需要找出JexlContext是什么(或应该是什么);在此基础上,可以直接迭代变量(从脚本中提取)并检查它们的值(从上下文中)。

请参阅:http://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/JexlContext.html http://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/JexlScript.html

例如(使用来自https://github.com/apache/commons-jexl的JEXL3.2主干):

代码语言:javascript
复制
/**
 * Collect the global variables of a script and their values from a context.
 * @param script the script
 * @param context the context
 * @return a map keyed by variable name of their contextual values
 */
Map<String, Object> collectVars(JexlScript script, JexlContext context) {
    Set<List<String>> sls = script.getVariables();
    Map<String, Object> vars = new TreeMap<String, Object>();
    for(List<String> ls : sls) {
        // build the 'antish' name by concatenating
        StringBuilder strb = new StringBuilder();
        for(String s : ls) {
            if (strb.length() > 0) {
                strb.append('.');
            }
            strb.append(s);
        }
        String name = strb.toString();
        vars.put(name, context.get(name));
    }
    return vars;
}

@Test
public void testStckOvrflw() throws Exception {
    JexlEngine jexl = new JexlBuilder().safe(false).create();
    // a context with some variables
    JexlContext context = new MapContext();
    context.set("low", 15000);
    context.set("high", 50000);
    context.set("mid", 35000);
    context.set("limit.low", 15042);
    context.set("limit.high", 35042);
    // an expression with 2 variables
    JexlScript expr = jexl.createScript("low >= 12345 && high <= 56789");
    // collecting the 2 variables, low and high
    Map<String, Object> vars = collectVars(expr, context);
    Assert.assertEquals(2, vars.size());
    Assert.assertEquals(15000, vars.get("low"));
    Assert.assertEquals(50000, vars.get("high"));

    expr = jexl.createScript("limit.low >= 12345 && limit.high <= 56789");
    vars = collectVars(expr, context);
    Assert.assertEquals(2, vars.size());
    Assert.assertEquals(15042, vars.get("limit.low"));
    Assert.assertEquals(35042, vars.get("limit.high"));
}
票数 1
EN

Stack Overflow用户

发布于 2020-01-21 18:17:23

您应该实现自己的上下文:

代码语言:javascript
复制
public class ZenContext implements JexlContext {
  static private final Map<String, Object> reservedVars = new HashMap<String, Object>();
  private final Map<String, Object> scriptDefinedVars  = new HashMap<String, Object>();
  static {
    reservedVars.put("math", java.lang.Math.class);
    reservedVars.put("stats", apache.commons.math3.stats.Stats);
    // whatever else ...
  }

  public boolean has(String name) {
    if (reservedVars .get(name) != null) return true;
    return scriptDefinedVars.get(name) != null;
  }

  public boolean get (String name) {
    Object value = null;
    if ((value = reservedVars .get(name)) != null) return value;

    return scriptDefinedVars.get(name);
  }

  public void set(String name, Object value) {
    scriptDefinedVars.set(name, value);
  }

  public Map<String, Object> getReservedVars () {
    return reservedVars;
  }
  public Map<String, Object> getScriptDefinedVars   () {
    return scriptDefinedVars ;
  }
}

在这种情况下,您将拥有

  • 保留变量名称的映射以包含您不允许脚本更改其值的对象。例如,
  • 可以从脚本中设置的变量的单独映射。

然后添加这些方法。

代码语言:javascript
复制
public Object execute(File scriptFile) {
    JexlScript script = jexlEngine.createScript(scriptFile);
    return script.execute(this); // supply this as the context 
}
public Object execute (String scriptText) {
    JexlScript script = jexlEngine.createScript(scriptText);
    return script.execute(this); // supply this as the context 
}

您可以修改我在这里编写的set方法,以便在允许设置变量之前检查映射中的变量。

但是,这不适用于本地脚本变量

代码语言:javascript
复制
var greeting = 'The rain in Maine falls plainly insane';

因为local var依赖于一种不同的机制,即使用getLocalVariables()方法的org.apache.commons.jexl3.internal.Scope,该方法有一个错误。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53728673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档