JEXL表达式引擎

JEXL表达式引擎

源码地址:https://github.com/TomFrost/Jexl

官方文档:https://commons.apache.org/proper/commons-jexl/reference/syntax.html

简介

JEXL(Java Expression Language)是一种基于Java的表达式语言,可以在Java程序中使用它来计算表达式的值。它支持常见的算数运算、逻辑运算、比较运算、条件运算变量和函数、数组与集合、正则表达式等。可以帮助开发人员在Java程序中使用表达式来计算值并实现更灵活和复杂的操作。

常用的表达式语法

一元运算符

OperationSymbol
Negate!

二元运算符

OperationSymbol
Add, Concat+
Subtract-
Multiply*
Divide/
Divide and floor//
Modulus%
Power of^
Logical AND&&
Logical OR||

比较

ComparisonSymbol
Equal==
Not equal!=
Greater than>
Greater than or equal>=
Less than<
Less than or equal<=
Element in array or stringin
关于in的注释

in运算符可用于检查子字符串: "Cad" in "Ron Cadillac",也可用于检查数组元素: "coarse" in ['fine', 'medium', 'coarse']。但是,该==运算符在幕后用于搜索数组,因此不应将其与对象数组一起使用。以下表达式返回 false:{a: 'b'} in [{a: 'b'}]

三元运算符

条件表达式检查第一个段的计算结果是否为真值。如果是,则评估随后的段。否则,替代方案是。如果后续部分丢失,则将使用测试结果本身。

ExpressionResult
“” ? “Full” : “Empty”Empty
“foo” in “foobar” ? “Yes” : “No”Yes
{agent: “Archer”}.agent ?: “Kane”Archer

原生类型

TypeExamples
Booleanstrue, false
Strings“Hello “user””, ‘Hey there!’
Numerics6, -7.2, 5, -3.14159
Objects{hello: “world!”}
Arrays[‘hello’, ‘world!’]

括号

括号的作用正如我们所期望的那样:

表达结果
(83 + 1) / 242
1 < 3 && (4 > 2 || 2 > 4)真的

其他

JEXL还支持类似Java语言的语法,比如在字符串前面加上$ 变量引用

  • Hello,${name}

可以使用.来调用对象的方法和属性

  • object.property

可以支持数组和集合,可以使用[]访问元素

  • list[index]。

另外,JEXL还支持正则表达式,可以使用~=~!进行匹配和不匹配的操作

  • string~=/pattern/
  • string!=/pattern/

在代码中集成JEXL

pom依赖

<!-- Jexl表达式引擎依赖 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-jexl3</artifactId>
    <version>3.2.1</version>
</dependency>

自定义工具类

package com.hand.hap.core.util;

import org.apache.commons.jexl3.*;

import java.math.BigDecimal;
import java.util.Map;

/**
 * JexlExpression util
 *
 * @author linwy
 */
public class JexlExpressionUtil {

    private static final JexlContext INSTANCE;

    static {
        // Initialize the INSTANCE JexlContext with the BigDecimal variable
        MapContext mapContext = new MapContext();
      	// BigDecimal类方法支持 如果需要其他类方法的支持 引入方式同下
        mapContext.set("BigDecimal", BigDecimal.class);
        INSTANCE = mapContext;
    }

    public static synchronized JexlContext getInstance() {
        return INSTANCE;
    }

    private JexlExpressionUtil(){
        
    }

    /**
     * 将字符串公式转换成可执行代码
     *
     * @param formula 计算公式
     * @param param   参数Map<参数名, 参数值>
     * @return 计算结果
     */
    public static BigDecimal convertToCode(String formula, Map<String, BigDecimal> param) {
        JexlExpression expression = new JexlBuilder().create().createExpression(formula);
        JexlContext jc = JexlExpressionUtil.getInstance();
        // 转换参数
        param.forEach((k, v) -> jc.set(k, v != null ? v : BigDecimal.ZERO));
        // 执行计算
        Object obj = expression.evaluate(jc);
        BigDecimal result = obj == null ? BigDecimal.ZERO : new BigDecimal(obj.toString());
        return result.setScale(2, RoundingMode.HALF_UP);
    }

}

测试demo

    public static void main(String[] args){
        String calculateRule = "amount-(amount/(1+taxRate)*taxRate).setScale(2, BigDecimal.ROUND_HALF_UP)";
        Map<String, BigDecimal> param = new HashMap<>();
        param.put("amount",  new BigDecimal("1230"));
        param.put("taxRate", new BigDecimal("0.06"));
        System.out.println(JexlExpressionUtil.convertToCode(calculateRule,param));
    }

输出结果

1160.38

Process finished with exit code 0
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值