jexl3动态计算表达式

  • 背景

Java Expression Language (JEXL) 是一个表达式语言引擎,可以用来在应用或者框架中使用。JEXL 受Velocity 和 JSP 标签库 1.1 (JSTL) 的影响而产生的。需要注意的是, JEXL 并不是 JSTL 中的表达式语言的实现。

  • 使用场景

  1. 实时引擎里

  1. 动态逻辑计算分离

  1. 计算逻辑经常变化或者可视化逻辑配置

  • 学习实例

  • 引入JAR包

引入Maven包,我这里使用版本最新版本3.2.1版本号。

       <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-jexl3</artifactId>
            <version>3.2.1</version>
        </dependency>
  • 第一个实例

通过一个用户在商场购买香蕉、苹果来计算总金额为程序计算场景。苹果5.6一斤、香蕉7.2一斤;用户买2斤苹果,3斤香蕉

JexlBuilder jexlBuilder = new JexlBuilder();
JexlEngine jexlEngine = jexlBuilder.create();
//苹果5.6一斤、香蕉7.2一斤;用户买2斤苹果,3斤香蕉
String expressionStr = "2*5.6+7.2*3";
JexlExpression expression = jexlEngine.createExpression(expressionStr);
MapContext mapContext = new MapContext();
Object evaluate = expression.evaluate(mapContext);
System.out.println(String.format("应支付金额:%s", evaluate));
  • 变量计算实例

通过MapContext把表达式需要值传送变量到表达式里,完成用户应付金额。

JexlBuilder jexlBuilder = new JexlBuilder();
JexlEngine jexlEngine = jexlBuilder.create();
//苹果5.6一斤、香蕉7.2一斤;用户买2斤苹果,3斤香蕉
String expressionStr = "applePrice*appleTotal+bananaPrice*bananaTotal";
JexlExpression expression = jexlEngine.createExpression(expressionStr);
MapContext mapContext = new MapContext();
mapContext.set("applePrice", 5.6);
mapContext.set("appleTotal", 2);
mapContext.set("bananaPrice", 7.2);
mapContext.set("bananaTotal", 3);
Object evaluate = expression.evaluate(mapContext);
System.out.println(String.format("用用应支付金额:%s", evaluate));
  • 访问对象实例

我们在应该开发时,我们的数据一般封装为JAVA对象,我们在表达式中可以访问与设置对象的值。

JexlBuilder jexlBuilder = new JexlBuilder();
JexlEngine jexlEngine = jexlBuilder.create();
//苹果5.6一斤、香蕉7.2一斤;用户买2斤苹果,3斤香蕉
String expressionStr = "applePrice*appleTotal+bananaPrice*bananaTotal";
JexlExpression expression = jexlEngine.createExpression(expressionStr);
MapContext mapContext = new MapContext();
mapContext.set("applePrice", 5.6);
mapContext.set("appleTotal", 2);
mapContext.set("bananaPrice", 7.2);
mapContext.set("bananaTotal", 3);
Object evaluate = expression.evaluate(mapContext);
System.out.println(String.format("应支付金额:%s", evaluate));

定义商品订单对象为

public class OrderDto implements Serializable {
    private Double totalPrice;
    private List<OrderItemDto> orderItems;

    public Double getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(Double totalPrice) {
        this.totalPrice = totalPrice;
    }

    public List<OrderItemDto> getOrderItems() {
        return orderItems;
    }

    public void setOrderItems(List<OrderItemDto> orderItems) {
        this.orderItems = orderItems;
    }

    public static class OrderItemDto {
        private Double price;
        private Integer num;
        private String name;

        public OrderItemDto(Double price, Integer num, String name) {
            this.price = price;
            this.num = num;
            this.name = name;
        }

        public OrderItemDto() {
        }

        public OrderItemDto(Double price, Integer num) {
            this.price = price;
            this.num = num;
        }

        public Double getPrice() {
            return price;
        }

        public void setPrice(Double price) {
            this.price = price;
        }

        public Integer getNum() {
            return num;
        }

        public void setNum(Integer num) {
            this.num = num;
        }
    }
  • 自定义函数

在业务开发中,我们使用表达式计算不一定满足我们业务需要,我们可以在我们表达式使用自己开发的方法,计算应付金额通过函数来完成。

public class PriceFunction {
    /**
     * 函数名称
     *
     * @return 名称
     */
    String functionName() {
        return "priceFunction";
    }

    /**
     * 计算结果
     *
     * @param arg 参数
     * @return 返回值
     */
   public static Object   excute(List<OrderDto.OrderItemDto> arg) {
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        double totalPrice = 0.0D;
        for (OrderDto.OrderItemDto dto: arg) {
            totalPrice += dto.getPrice() * dto.getNum();
        }
        return  totalPrice;
    }
}

计算表达式

JexlBuilder jexlBuilder = new JexlBuilder();
Map<String, Object> functions = new HashMap<>();
functions.put("cacl", new PriceFunction());
jexlBuilder.namespaces(functions);
JexlEngine jexlEngine = jexlBuilder.create();
//苹果5.6一斤、香蕉7.2一斤;用户买2斤苹果,3斤香蕉
OrderDto orderDto = new OrderDto();
List<OrderDto.OrderItemDto> orderItemDtos = new ArrayList<>();
orderItemDtos.add(new OrderDto.OrderItemDto(5.6, 2, "苹果"));
orderItemDtos.add(new OrderDto.OrderItemDto(7.2, 3, "香蕉"));
orderDto.setOrderItems(orderItemDtos);
String expressionStr = "cacl:excute(order.orderItems)";
JexlExpression expression = jexlEngine.createExpression(expressionStr);
MapContext mapContext = new MapContext();
mapContext.set("order", orderDto);
Object evaluate = expression.evaluate(mapContext);
System.out.println(String.format("应支付金额:%s", evaluate));
  • 三元表达式实例

        JexlBuilder jexlBuilder = new JexlBuilder();
        JexlEngine jexlEngine = jexlBuilder.create();
        //3元表达式
        String expressionStr = "(1< 2)? '真':'假'";
        JexlExpression expression = jexlEngine.createExpression(expressionStr);
        MapContext mapContext = new MapContext();
        Object evaluate = expression.evaluate(mapContext);
        System.out.println(String.format("结果:%s", evaluate));
  • IF/FOR语法支持

        JexlBuilder jexlBuilder = new JexlBuilder();
        Log log = LogFactory.getLog(JexDemoGrammar.class);
        JexlEngine jexlEngine = jexlBuilder.logger(log).create();
        //IF判断表达式
        String expressionStr = "if(1< 2){ return '真';}else{ return '假';}";
        JexlScript expression = jexlEngine.createScript(expressionStr);
        MapContext mapContext = new MapContext();

        Object evaluate = expression.execute(mapContext);
        System.out.println(String.format("结果:%s", evaluate));
        //For 循环
        String expressionFor = "while (i lt  100) {  i = i + 1;total = total + i;}";
        JexlScript scriptFor = jexlEngine.createScript(expressionFor);
        MapContext context = new MapContext();
        context.set("len", 100);
        context.set("total", 0);
        context.set("i", 0);
        context.set("log", log);
        Object execute = scriptFor.execute(context);
        System.out.println(String.format("结果:%s", execute));

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值