性能文章>java解析表达式Jexl>

java解析表达式Jexl原创

255312

前言

在项目中,我们可以使用一些表达式来判断是否需要触发警告。例如一些常见的表达式及其含义:

  1. 条件表达式:这是最基本的表达式,用于判断某个条件是否成立。例如:

    if (x > 10) {
      // do something
    }
    

    这个表达式会判断变量 x 是否大于 10,如果成立,则执行 do something

  2. 逻辑表达式:这种表达式通常用于将多个条件组合起来,判断整个表达式的结果是真还是假。例如:

    if (x > 10 && y < 20) {
      // do something
    }
    

    这个表达式会判断变量 x 是否大于 10 并且变量 y 是否小于 20,如果成立,则执行 do something

导论

接着就找到了脚本引擎java自带的ScriptEngine,Java自带的ScriptEngine是一个灵活的工具,可以用来执行不同的脚本语言,包括JavaScript、Python等。以下是一些ScriptEngine的总结:

  1. ScriptEngine支持多种脚本语言,包括JavaScript、Python等,通过设置不同的脚本引擎可以执行不同的脚本语言。

  2. 在执行脚本之前,需要先创建ScriptEngine对象,并且指定所需要的脚本引擎。

  3. ScriptEngine可以解析并执行字符串、文件等各种类型的脚本,执行的结果可以获取并处理。

  4. 通过调用ScriptEngine的eval方法可以执行脚本。

  5. ScriptEngine还提供了一些其他的方法,例如:compile用于编译一段脚本,get和put用于在脚本中获取和设置变量等。

  6. 在使用ScriptEngine时需要注意脚本语言的语法及执行环境的安全性,避免脚本中出现恶意代码。

总之,ScriptEngine是一个非常方便的工具,可以帮助Java程序员使用不同的脚本语言,实现更高效的编程。接着就开始

    @Test
    public void test2() {
      
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
// String script = "function add(a, b) { return a + b; } add(x, y);";
// String script = " !x.contains('hello') ";
// String script = "'hello world'.contains('x') ";
// String script = "'x'.contains('hello world') ";
        String script = "'asddshelloworld'.indexOf(x) != -1";
// String script = "value > 10";
// String script = "'sfjldsjf'.includes('x') ";
// String script = " x == 'hello world' ";
        try {
      
            Bindings bindings = engine.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
            bindings.put("x", "hello");
// bindings.put("value", "100");
// bindings.put("#", 2);
            Object result = engine.eval(script, bindings);
            System.out.println(result);
        } catch (ScriptException e) {
      
            e.printStackTrace();
        }
    }    public void test2() {
      
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
// String script = "function add(a, b) { return a + b; } add(x, y);";
// String script = " !x.contains('hello') ";
// String script = "'hello world'.contains('x') ";
// String script = "'x'.contains('hello world') ";
        String script = "'asddshelloworld'.indexOf(x) != -1";
// String script = "value > 10";
// String script = "'sfjldsjf'.includes('x') ";
// String script = " x == 'hello world' ";
        try {
      
            Bindings bindings = engine.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
            bindings.put("x", "hello");
// bindings.put("value", "100");
// bindings.put("#", 2);
            Object result = engine.eval(script, bindings);
            System.out.println(result);
        } catch (ScriptException e) {
      
            e.printStackTrace();
        }
    }

但是却一直提示未来会删除,这就像一个TODO一样环绕心头,是个待解决的bug,目前使用的jdk11,测试了jdk17发现,类都没了,这还限制了不能升级。

Warning: Nashorn engine is planned to be removed from a future JDK release

后续

偶然的巧合下,发现了jex这个包完美适配我现在的代码哈哈,也不存在未来被移除的风险,挺好真的!同时也发现Spring的SpEL表达式,SpEL(Spring Expression Language)是Spring框架中的一种表达式语言,它提供了一种在运行时定义表达式的方法,可以用于Spring中的各种注解中,也可以用于XML或Java配置中。
以下是SpEL的介绍:

  1. 基本语法: SpEL的基本语法是#{expression},其中expression可以是任何有效的表达式。

  2. 变量:可以在SpEL中定义变量,并在表达式中引用它们。例如:#{T(java.lang.Math).PI}表示引用Math类的PI常量。

  3. 属性:可以在SpEL中引用对象的属性。例如:#{person.name}表示引用person对象的name属性。

  4. 方法调用:可以在SpEL中调用对象的方法。例如:#{person.getName()}表示引用person对象的getName方法。

  5. 运算符:SpEL支持各种运算符,如算术、比较、逻辑、赋值等。

  6. 集合:可以在SpEL中引用集合,并对其进行操作。例如:#{list.size()}表示引用list集合的大小。

  7. 正则表达式:可以在SpEL中使用正则表达式进行匹配操作。例如:#{‘Spring Framework’.matches(‘.Frame.’)}表示判断字符串中是否包含"Frame"。

总之,SpEL为Spring框架提供了一种强大的表达式语言,可以在配置文件中使用它来定义各种复杂的表达式,提高了系统的可配置性和可扩展性。

而另外的Jexl表达式,Jexl是基于Java的表达式语言,可以方便的进行文本、数值、逻辑等计算,还可以对对象进行操作和访问。以下是Jexl使用的总结:

  1. 导入Jexl库:可以通过maven或者手动导入Jexl库。

  2. 创建Jexl表达式:可以通过JexlEngine创建Jexl表达式。

  3. 执行Jexl表达式:可以通过JexlExpression的evaluate方法执行Jexl表达式。

  4. 定义变量和属性:可以通过JexlContext定义变量和属性,可以通过变量名或属性名获取对应的值。

  5. 支持的运算符:支持标准的加减乘除等基本运算符,也支持比较和逻辑运算符。

  6. 支持访问对象属性和方法:可以通过.和[]来访问属性和方法,还可以使用@符号来获取类的静态属性和方法。

  7. 支持执行条件语句和循环语句:可以通过if、else、for和while等语句来实现条件和循环控制。

  8. 支持自定义函数:可以通过实现JexlContext.Function接口来自定义函数,并将函数注册到JexlContext中。

  9. 支持Lambda表达式:从Jexl 3.1开始,支持Lambda表达式,可以使用箭头函数来创建匿名函数。

总的来说,Jexl是一个功能强大、易于使用的表达式语言库,适用于从简单的计算到复杂的数据处理和业务逻辑场景。
步骤:
需要导入的包

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-jexl3</artifactId>
            <version>3.2.1</version>
        </dependency>

commons-jexl3是一个Java工具包,它提供了一种简单的脚本语言,用于在Java应用程序中执行动态表达式。它基于JEXL2,并提供了许多新特性和改进。这个工具包可以帮助开发人员更轻松地实现动态表达式的执行和管理。

demo1

@Test
public void mainDemoOne() {
      
        // 创建一个 JexlEngine 对象
        JexlEngine jexl = new JexlBuilder().create();

        // 创建一个 JexlExpression 对象
        String expression = " (foo<bar ) and (2>3)";
        JexlExpression e = jexl.createExpression(expression);

        // 使用 Jexl 执行表达式
        JexlContext context = new MapContext();
        context.set("foo", 1);
        context.set("bar", 2);
        try {
      
            Object result = e.evaluate(context);
            System.out.println("Result: " + result);
        } catch (JexlException ex) {
      
            System.err.println("Error: " + ex.getMessage());
        }
    }

demo2
测试文本包含情况

    @Test
    public void testDemoTwo() {
      
        JexlEngine jexl = new JexlBuilder().create();
        JexlContext context = new MapContext();
        context.set("input", "xyzabcdefg");
        String expression = "input.contains('abc')";
        JexlExpression jexlExpression = jexl.createExpression(expression);
        boolean result = (boolean)jexlExpression.evaluate(context);
        System.out.println(result);
    }

总结

这些偏门的表达式还是孤陋寡闻了,细分领域还是要多多涉足,多多逛逛开源社区,积累总计,指不定什么时候就用上了。没了之前的未来删除的忧愁,痛快哈哈!

引用

Java | 在 Java 中执行动态表达式语句: 前中后缀、SpEL、OGNL、Groovy、Jexl3

点赞收藏
分类:标签:
查拉图斯特拉说

让世界因你而不同

请先登录,查看1条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

随机一门技术分享之Netty

随机一门技术分享之Netty

从 Linux 内核角度探秘 JDK MappedByteBuffer

从 Linux 内核角度探秘 JDK MappedByteBuffer

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

2
1