为了账号安全,请及时绑定邮箱和手机立即绑定

在 JEXL 中获取表达式值

在 JEXL 中获取表达式值

ABOUTYOU 2022-03-10 15:48:27
具有以下 JEXL 表达式:String expression = "myVar >= 12345 && mySecondVar <= 56789";我可以调用 createScript 和 getVariables 来获取 myVar 和 mySecondVar 作为值,例如:Set<List<String>> expressionVars = JEXL.createScript(expression).getVariables();我想知道的是,如果给定相同的表达式,我可以调用一些其他方法来返回这些变量的值。原因是我想验证其中一些值的输入。我检查了文档并使用了 JexlScript 类,但找不到一种优雅的方法。由于 JEXL 已经在解析我的表达式,因此能够检索此信息并且不必手动解析我的表达式来获取此值将是非常棒的。script.getValue("myVar");正在返回的东西12345
查看完整描述

2 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

使用 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的 JEXL 3.2 主干):


/**

 * 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"));

}


查看完整回答
反对 回复 2022-03-10
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

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


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 ;

  }

}

这样,您将拥有


保留 var 名称的映射,以包含不允许脚本更改其值的对象。例如,

可以从脚本设置的单独的变量映射。

然后添加这些方法。


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 方法,以检查映射中的变量,然后再允许它们设置。


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


var greeting = 'The rain in Maine falls plainly insane';

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


查看完整回答
反对 回复 2022-03-10
  • 2 回答
  • 0 关注
  • 438 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号