寻找JEXL过滤器功能

时间:2018-04-20 04:16:50

标签: java filtering jexl

我知道,我可以在JEXL中执行多项操作,但无法在其中找到过滤器功能,这确实非常有用。

我该怎么做

<form class="box-login">

  <div class="box-inputs">
    <label class="box-input" for="cpf"></label>
    <input class="line-input" id="cpf" type="text" placeholder="CPF">
  </div>

  <div class="box-inputs">
    <label for="box-input">
            <input class="line-input" id="password" type="password" placeholder="Senha">
            </label>

  </div>
  <div>
    <button class="btn-login">ENTRAR</button>
  </div>
</form>

1 个答案:

答案 0 :(得分:2)

首先,您的语法无效JEXL。我猜你是这个意思:

var x = [{'a':11,'b':5}, {'a':1,'b':15}, {'a':12,'b':25}, {'a':4,'b':35}, {'a':7,'b':45}];

由于您可以在JEXL脚本中的任何对象上调用任何Java方法,因此您(至少在理论上)可以完全访问Java Stream API。

但是,Stream API不能直接从原始数组中获取,我们不能在不费力的情况下调用Arrays.stream(x);。最简单的方法是创建一个集合:

var x = {{'a':11,'b':5}, {'a':1,'b':15}, {'a':12,'b':25}, {'a':4,'b':35}, {'a':7,'b':45}};

现在我们只需致电stream()并从那里开始工作:

x.stream();

我们现在想要的是这样的:

x.stream().filter(function(m){m['a']>10});

不幸的是,JEXL中的方法解析器无法使用JEXL函数正确解析Stream.filter(Predicate),因为它不知道如何将JEXL函数转换为Predicate。 JEXL函数的类型为org.apache.commons.jexl3.internal.Closure

因此,您至少需要做的是在Java中提供自己的Predicate实现,然后在脚本中创建一个新实例:

public class MyCustomFilterPredicate implements Predicate<HashMap<String, Integer>> {
    @Override
    public boolean test(final HashMap<String, Integer> m)
    {
        return m.get("a") > 10;
    }
}

然后,您可以在JEXL脚本中创建一个新实例:

var filterPredicate = new('my.custom.filter.predicate.MyCustomFilterPredicate');

同样适用于Stream.map(Function)

public class MyCustomMapFunction implements Function<HashMap<String, Integer>, Integer> {
    @Override
    public Integer apply(final HashMap<String, Integer> m)
    {
        return m.get("b");
    }
}

再次在脚本中创建一个新实例:

var mapFunction = new('my.custom.map.function.MyCustomMapFunction');

您的整个脚本将如下所示:

var x = {{'a':11,'b':5}, {'a':1,'b':15}, {'a':12,'b':25}, {'a':4,'b':35}, {'a':7,'b':45}};

var filterPredicate = new('my.custom.filter.predicate.MyCustomFilterPredicate');
var mapFunction = new('my.custom.map.function.MyCustomMapFunction');

return x.stream().filter(filterPredicate).map(mapFunction).toArray();

当然,您可能已经注意到谓词和函数实现的可重用性相当有限。这就是为什么我建议创建包装JEXL Closure的实现:

public class MyCustomFilterPredicate implements Predicate<Object> {
    private final Closure closure;
    public MyCustomFilterPredicate(final Closure closure) {
        this.closure = closure;
    }
    @Override
    public boolean test(final Object o)
    {
        return (boolean) closure.execute(JexlEngine.getThreadContext(), o);
    }
}

public class MyCustomMapFunction implements Function<Object, Object> {
    private final Closure closure;
    public MyCustomMapFunction(final Closure closure) {
        this.closure = closure;
    }
    @Override
    public Object apply(final Object o)
    {
        return closure.execute(JexlEngine.getThreadContext(), o);
    }
}

现在,您可以按如下方式更改脚本,并以各种方式重用这些Java类:

var x = {{'a':11,'b':5}, {'a':1,'b':15}, {'a':12,'b':25}, {'a':4,'b':35}, {'a':7,'b':45}};

var filterPredicate = new('my.custom.filter.predicate.MyCustomFilterPredicate', function(m){m['a']>10});
var mapFunction = new('my.custom.map.function.MyCustomMapFunction', function(m){m['b']});

return x.stream().filter(filterPredicate).map(mapFunction).toArray();