Java expression engine selection research and analysis | JD Cloud technical team

1 Introduction

Our project team is mainly responsible for business systems for enterprise customers. The needs of enterprises are often diverse and complex. When connecting with different enterprises, they will have different customized business models and processes. We use expression engines in business systems to centrally configure and manage business rules and implement real-time decision-making and calculations, which can improve the flexibility and responsiveness of the system to better meet business needs.

As a simple example, suppose we have a business scenario. In the rebate system, when a promoter meets certain reward conditions, the corresponding reward amount will be given to him. For example, the specific reward rules for a certain product are as follows:

Reward conditions Reward amount
The number of new users is greater than or equal to 3 and the unit price is greater than 50 yuan 100 yuan
The number of new users is greater than or equal to 5 and the unit price is greater than 100 yuan 200 yuan
The number of new users is greater than or equal to 10 and the unit price is greater than 200 yuan 500 yuan

This rule seems easy to implement, just write a few if else branches in the code. But what if the rebate system is connected to multiple suppliers, and each company provides different products with different reward rules? It seems not good to write if else in a hard-coded way. Every time you add, modify or delete rules, you need to release the system online.

The introduction of a rule engine seems to be able to solve this problem. One benefit of the rule engine is that it can separate business rules and business code, thereby reducing the difficulty of maintenance. At the same time, it can also meet the demands of business personnel by writing DSL or specifying rules through the interface, so that The idea that rules can be established without developer involvement may sound reasonable, but in practice it rarely works. First of all, the rule engine has a certain learning cost. Even developers need to do special learning when using it, not to mention business personnel without any programming background. Secondly, the complexity of its implementation is also high. If the business rules are complex, the rule makers will If you don’t understand the hidden program flow inside the rule engine, you may get unexpected results. Finally, some rule engines still have performance bottlenecks. If you are not familiar with the rule engine and the expression engine, and the abstracted business rules need to be formulated by developers, then the expression engine is much easier to use, its syntax is closer to Java, and some The expression engine will also compile expressions into bytecode, which may have more advantages in terms of execution speed and resource utilization. **So, for this type of business scenario, it seems more appropriate to use the expression engine.

This article mainly provides a brief introduction and analysis of the Java expression engine, and provides certain suggestions to provide input for the technical selection of the expression engine during the team's research and development process.

2 Introduction to technology stack

This article will conduct a selection survey on several common expression engines such as AviatorScript , MVEL , OGNL , SpEL , QLExpress , JEXL , and JUEL . First, let’s briefly introduce these expression engines.

2.1 AviatorScript

AviatorScript is a high-performance, lightweight scripting language hosted on the JVM. AviatorScript compiles expressions into bytecode. In 2010, the author developed and open sourced the Notify internal message middleware when he was responsible for Taobao middleware. Its original positioning has always been just an expression engine, which does not support if/else conditional statements, nor does it support for/while loop statements, etc. With the release of 5.0, it has transformed into a general scripting language and supports these language features.

Documentation: https://www.yuque.com/boyan-avfmj/aviatorscript

2.2 MVEL (MVFLEX Expression Language)

MVEL is a mixed dynamic/static type expression language that can be embedded in the Java platform. MVEL is used by many Java projects. MVEL is heavily inspired by Java syntax, but there are some fundamental differences intended to make it more efficient as an expression language, such as direct support for operators for collections, arrays, and string matching, as well as regular expressions. The earliest version was released in 2007.

Documentation: http://mvel.documentnode.com/

2.3 OGNL (Object-Graph Navigation Language)

OGNL stands for Object-Graph Navigation Language; it is an expression language used to get and set properties of Java objects, as well as other extra features such as list projection and selection and lambda expressions. Version 2.1.4 was released in 2005.

Documentation: https://commons.apache.org/dormant/commons-ognl/language-guide.html

2.4 SpEL (Spring Expression Language)

SpEL is a powerful expression language that supports querying and manipulating object graphs at runtime. The language's syntax is similar to Unified EL, but provides more functionality, chief among which are method calls and basic string template functionality.

Documentation: https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#expressions

2.5 QLExpress

A dynamic script engine parsing tool designed based on Alibaba's strong needs for e-commerce business rules, expressions (Boolean combinations), special mathematical formula calculations (high precision), syntax analysis, and secondary script customization, it was open sourced in 2012.

Documentation: https://github.com/alibaba/QLExpress

2.6 JEXL (Java Expression Language)

JEXL is designed to facilitate dynamic scripting capabilities in applications and frameworks written in Java. JEXL implements an expression language based on some extensions to the JSTL expression language and supports most ideas in shell scripts or ECMAScript. Version 1.0 was released in 2005.

Documentation: https://commons.apache.org/proper/commons-jexl/reference/syntax.html

2.7 JUEL (Java Unified Expression Language)

JUEL is an implementation of Unified Expression Language (EL), which is part of the JSP 2.1 standard (JSR-245) and was introduced in JEE5. In addition, JUEL 2.2 implements the JSP 2.2 maintenance version specification and is fully compliant with the JEE6 standard. Version 2.1.0 was released in 2006, and 2.2.7 was released in 2014.

Documentation: https://juel.sourceforge.net/guide/start.html

2.8 Ioannina

Janino is an ultra-small and ultra-fast Java compiler that can also be used as an expression engine. Its performance is very good. According to the official website, excellent open source projects such as Apache Spark, Apache Flink, and Groovy all use Janino.

Documentation: http://janino-compiler.github.io/janino/

Since Janino is actually a Java compiler, its performance should theoretically be closer to directly executing Java code. Secondly, it is more complicated to use as an expression engine. Therefore, in the following comparison, Janino does not participate in the comparison and can be used as a reference.

2.9 Others

Although some of the following expression engines are also commonly seen on various technology blogs, they are not included in this selection comparison because they have not been updated and maintained for a long time.

Up

Fel is a lightweight and efficient expression calculation engine. Fel originated from enterprise projects and was designed to meet changing functional and performance requirements. The project is hosted on Google Code. The last update was in 2012. It has not been updated for more than ten years, so it was not included in this selection.

I-expression

IK Expression is an open source (OpenSource), extensible (Extensible), super lightweight (Super lightweight) formulaic language parsing execution toolkit developed based on the Java language. The first version was released in February 2009, and no new version was released after the last version was released in October 2009, so it was not included in this selection.

YOU WERE

JSEL is a simple expression interpretation engine compatible with JavaScript operation rules. You can give a variable set through the Map interface or JavaBean, and then extract variables from this set through expressions, and then use expression logic to generate what you need. data. The first version was released in 2009, and the last version was released in 2011 and has not been updated, so it is not included in this selection.

In addition, rule engines such as Drools, urule, and easy-rules do not participate in this selection comparison. Relatively mature and complete scripting languages ​​such as Groovy are not included in the selection comparison. This article focuses on selecting a relatively lightweight and simple expression engine.

3 Technology stack selection evaluation

When choosing an expression engine, we want it to have good community support, moderate implementation complexity, fast execution, security, and be easy to learn. Therefore, the next step will be to compare and evaluate several expression engines from the aspects of community support, introduced size and dependencies, performance, security, use cases and syntax.

3.1 Community support

Community support can help evaluate the health of the project, whether problems can be solved in time, whether the project can continue to evolve, etc. The following is a list of GitHub star, watch, fork, last commit and other data, which can be used as a reference. Due to the data Changes will occur over time, and the following analysis is only based on the data of 2023.10.29.

Since the Spring project is widely used and SpEl is a sub-project of Spring, SpEl's community support is the best from various data points. Let's first exclude several other expression engines from SpEl analysis.

QLExpress, AviatorScript and MVEL are widely used in China, which may be the reason for their high star, watch, and fork numbers. This shows that the popularity, recognition and influence of these projects should be relatively high.

Analyzing the number of issues and pull requests, we can see that MVEL, AviatorScript and QLExpress are higher than other script engines, indicating that they have more user needs and feedback, which may also mean that the project faces more problems and challenges.

MVEL, JEXL, and OGNL all have many contributors participating. Their community collaboration and project sustainability should be relatively good.

Based on the above analysis, except for SpEl, QLExpress, AviatorScript and MVEL have relatively good community support.

3.2 Introducing size and dependencies

Code size and dependencies can help evaluate the complexity of the code . The code size of each Github repository is listed below, which can be used as a reference (actual does not completely accurately reflect the complexity of its implementation).

The following is the data for 2023.10.29

JUEL and QLExpress have the smallest code sizes, both at more than 600 KB; followed by OGNL at a little more than 1MB; AviatorScript, MVEL, and JEXL are all about 2MB in size; SpEl is in the spring-framework warehouse, and the statistics in the above table are from spring-framework. The total size, simply looking at SpEl's module spring-expression, is about 1.3MB. But it also relies on spring-core and spring-jcl. If these two are included, the size will be about 7.4MB.

Let’s analyze it based on the dependencies of each project.

+- org.mvel:mvel2:jar:2.5.0.Final:compile
+- com.googlecode.aviator:aviator:jar:5.3.3:compile
+- com.alibaba:QLExpress:jar:3.3.1:compile
|  +- commons-beanutils:commons-beanutils:jar:1.8.2:compile
|  |  \- (commons-logging:commons-logging:jar:1.1.1:compile - omitted for conflict with 1.2)
|  \- commons-lang:commons-lang:jar:2.4:compile
+- org.codehaus.janino:janino:jar:3.1.10:compile
|  \- org.codehaus.janino:commons-compiler:jar:3.1.10:compile
+- ognl:ognl:jar:3.4.2:compile
|  \- org.javassist:javassist:jar:3.29.2-GA:compile
+- org.apache.commons:commons-jexl3:jar:3.3:compile
|  \- commons-logging:commons-logging:jar:1.2:compile
+- org.springframework:spring-expression:jar:5.3.29:compile
|  \- org.springframework:spring-core:jar:5.3.29:compile
|     \- org.springframework:spring-jcl:jar:5.3.29:compile
+- de.odysseus.juel:juel-api:jar:2.2.7:compile
+- de.odysseus.juel:juel-impl:jar:2.2.7:compile
+- de.odysseus.juel:juel-spi:jar:2.2.7:compile





In addition to SpEl, QLExpress, OGNL, and JEXL also have other dependencies.

If you consider the three dependencies of commons-beanutils, commons-lang, and commons-logging, the size introduced by QLExpress is about 10MB.

If you consider the javassist dependency, the size introduced by OGNL is more than 4MB.

If you consider the commons-logging dependency, the size introduced by JEXL is about 2.5MB.

Taken together, JUEL, AviatorScript, MVEL, and JEXL are better than others in terms of introduced size and dependencies.

3.3 Performance

Better performance means that the system can quickly respond to user requests, reduce waiting time, and improve experience.

In terms of performance, JMH is mainly used to test several expression engines in usage scenarios such as literal expressions, expressions containing variables, and expressions containing method calls.

JMH (Java Microbenchmark Harness) is a tool suite for code micro-benchmark testing. It is mainly based on method-level benchmark testing, and the accuracy can reach nanosecond level. This tool was written by Oracle's internal JIT experts, who should understand the impact of JIT and JVM on benchmarks better than anyone else.

Since the syntax or features of different expression engines are slightly different, the differences will be explained in the test below.

Performance test code address: GitHub

3.3.1 Literal expressions

1000 + 100.0 * 99 - (600 - 3 * 15) / (((68 - 9) - 3) * 2 - 100) + 10000 % 7 * 71

6.7 - 100 > 39.6 ? 5 == 5 ? 4 + 5 : 6 - 1 : !(100 % 3 - 39.0 < 27) ? 8 * 2 - 199 : 100 % 3

illustrate:

Since QlExpress reports an error when executing the second expression, parentheses need to be added. What is actually executed is6.7 - 100 > 39.6 ? (5 == 5 ? 4 + 5 : 6 - 1) : (!(100 % 3 - 39.0 < 27) ? 8 * 2 - 199 : 100 % 3)

Result analysis:

It can be clearly seen that the performance of the three expression engines JEXL, JUEL, and QlExpress is obviously not as good as other engines.

SpEl performs well when performing the first arithmetic operation, but is significantly inferior to AviatorScript, MVEL, and OGNL engines when performing the second nested ternary operation.

AviatorScript, OGNL, and MVEL performed well in this round of testing. AviatorScript and OGNL perform relatively well in executing both expressions, with AviatorScript slightly better than OGNL. MVEL performs best when performing the first arithmetic operation, but is slower than AviatorScript and OGNL engines when performing the second nested ternary operation.

3.3.2 Expressions containing variables

pi * d + b - (1000 - d * b / pi) / (pi + 99 - i * d) - i * pi * d / b

piDecimal * dDecimal + bDecimal - (1000 - dDecimal * bDecimal / piDecimal) / (piDecimal + 99 - iDecimal * dDecimal) - iDecimal * piDecimal * dDecimal / bDecimal

i * pi + (d * b - 199) / (1 - d * pi) - (2 + 100 - i / pi) % 99 == i * pi + (d * b - 199) / (1 - d * pi) - (2 + 100 - i / pi) % 99

(clientVersion == '1.9.0' || clientVersion == '1.9.1' || clientVersion == '1.9.2') && deviceType == 'Xiaomi' && weight >= 4 && osVersion == 'Android 9.0' && osType == 'Android' && clientIp != null && requestTime <= now&& customer.grade > 1 && customer.age > 18

illustrate:

  • Since different expression engines have differences in the underlying implementation of division when executing the second expression, MVEL, AviatorScript, and JEXL execute it. decimal.divide(otherDecimal, java.math.MathContext.DECIMAL128)Others are actually executed decimal.divide(otherDecimal, scale, roundingMode), but the parameters are slightly different, and they are grouped during analysis.
  • Since QlExpress reports an error when executing the third expression and does not support non-integer mod operations, type conversion needs to be added. What is actually executed isi * pi + (d * b - 199) / (1 - d * pi) - (int)(2 + 100 - i / pi) % 99 == i * pi + (d * b - 199) / (1 - d * pi) - (int)(2 + 100 - i / pi) % 99
  • Since AviatorScript reports an error when executing the fourth expression, the literal value of null is nil, and the actual execution is(clientVersion == '1.9.0' || clientVersion == '1.9.1' || clientVersion == '1.9.2') && deviceType == 'Xiaomi' && weight >= 4 && osVersion == 'Android 9.0' && osType == 'Android' && clientIp != nil && requestTime <= now&& customer.grade > 1 && customer.age > 18

Result analysis:

Arithmetic calculation SpEl of the 1st basic type wrapper class is optimal. Followed by AviatorScript, MVEL, OGNL. And JEXL, JUEL, QlExpress are not as good as other engines.

Arithmetic calculation of the second BigDecimal type. Due to different underlying implementations, they are divided into two groups. Group 1 MVEL, AviatorScript and JEXL, AviatorScript is better than MVEL and better than JEXL. Group 2 JUEL, QlExpress, OGNL and SpEl, the performance from best to worst is OGNL, SpEl, JUEL, QlExpress. Moreover, the performance of Group 1 is obviously worse than that of Group 2 due to its higher accuracy.

The third one contains a Boolean expression containing the basic type wrapper class arithmetic calculation. SpEl is the best, followed by AviatorScript, followed by OGNL, MVEL, JUEL, JEXL, and QlExpress.

The fourth contains a Boolean expression for string comparison. AviatorScript, MVEL, JEXL, OGNL perform better than JUEL, QlExpress, SpEl.

3.3.3 Expressions containing method calls

new java.util.Date()

s.substring(b.d)

s.substring(b.d).substring(a, b.c.e)

illustrate:

  • Since JUEL new java.util.Date()reports an error when executing and does not support new instances, the actual execution of this round is a custom function.fn:date()
  • Since AviatorScript s.substringreports an error when executing, it needs to use the internal functions provided by it. What is actually executed in this round is its internal function.string.substring
  • Result analysis:

SpEl performed best in this round of testing, even faster than Janino. MVEL, followed by AviatorScript, is better than AviatorScript when executing constructors. JEXL also performs relatively well. The three expression engines QlExpress, JUEL, and OGNL are not as good as other engines.

3.3.4 Summary

Based on the above test results, AviatorScript, SpEl, MVEL, and OGNL perform relatively well.

AviatorScript has relatively good performance and balanced performance, but its syntax is slightly different from other engines and Java.

Except for poor performance in some scenarios, SpEl performs very well in most scenarios, especially in literals, arithmetic calculations containing variables, and method calling scenarios.

MVEL's performance is relatively balanced. Arithmetic calculations involving variables are slightly worse than AviatorScript. It performs very well in literal arithmetic calculations and method calling scenarios.

OGNL's performance is also relatively balanced, but it performs poorly in method calling scenarios.

3.4 Security

When introducing an expression engine, attention should be paid to the security and reliability of the system, such as preventing malicious scripts from being injected in untrusted environments, executing certain system commands without permission, or causing applications to stop serving, etc. In terms of security, several expression engines are compared mainly through vulnerability disclosure, security guides and configurations.

3.4.1 Vulnerabilities

First, use keyword search to get a rough understanding of the vulnerabilities disclosed in different expression engines at https://cve.mitre.org/cve/search_cve_list.html . This method may not be very accurate. Due to the different usage scenarios, usage methods, and attention levels of different expression engines, there may be differences in the disclosed vulnerabilities. For example, the keywords of OGNL and SpEl that we are familiar with appear in vulnerabilities significantly more frequently than other expression engines. OGNL is used in MyBatis and Struts , and SpEl is widely used in Spring. These two expression engines are indirectly used by most projects and directly execute user input as part of the expression, which can easily lead to vulnerabilities .

From these published vulnerabilities, we can learn about possible security risks and their repairs in different expression engines, and try to avoid similar problems during use.

In addition, it is not recommended to directly open expression execution to untrusted environments. If it is really necessary, you should learn more about the selected expression engine and whether it provides the necessary setting options to avoid certain security risks.

name keyword link Number of vulnerabilities
AviatorScript https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=AviatorScript 1
MVEL https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=MVEL 4
OGNL https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=OGNL 28
Game https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=SpEl 10
QLExpress https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=QLExpress 0
JEXL https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=JEXL 3
JEWEL https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=JUEL 1

3.4.2 Security settings

AviatorScript, QLExpress, and JEXL all provide some security option settings to varying degrees.

AviatorScript

  • Set whitelist
// 在new语句和静态方法调用中允许使用的类白名单 默认 null 表示无限制
AviatorEvaluator.setOption(Options.ALLOWED_CLASS_SET, Sets.newHashSet(List.class));
// 在new语句和静态方法调用中允许使用的类白名单 包含子类 默认 null 表示无限制
AviatorEvaluator.setOption(Options.ASSIGNABLE_ALLOWED_CLASS_SET, Sets.newHashSet(List.class));

  • Prevent endless loops
// 循环最大次数 默认 0 表示无限制
AviatorEvaluator.setOption(Options.MAX_LOOP_COUNT, 10000);

  • Feature switch
// 关闭某些特性
AviatorEvaluator.getInstance().disableFeature(Feature.Module);
AviatorEvaluator.getInstance().disableFeature(Feature.NewInstance);
// 只开启需要的特性
AviatorEvaluator.setOption(Options.FEATURE_SET, Feature.asSet(Feature.If));

QLExpress

  • Enable sandbox mode
QLExpressRunStrategy.setSandBoxMode(true);

In sandbox mode it is not possible to:

import Java class
◦Explicit reference to a Java class, e.g.String a = 'mmm'
◦Get the fields in the Java class:a = new Integer(11); a.value
◦Call methods in Java classes:Math.abs(12)

Can:

◦Use QLExpress’s custom operators/maros/functions to achieve controlled interaction with the application
◦Use the . operator to obtain the value corresponding to the key of the Map. For example, if a is a Map in the expression passed in by the application, it can be obtained through ab.
◦All operations that do not involve applying Java classes
  • Set whitelist
// 设置编译期白名单
QLExpressRunStrategy.setCompileWhiteCheckerList(Arrays.asList(
    // 精确设置
    CheckerFactory.must(Date.class),
    // 子类设置
    CheckerFactory.assignable(List.class)
));
// 设置运行时白名单// 必须将该选项设置为 true
QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
// 有白名单设置时, 则黑名单失效
QLExpressRunStrategy.addSecureMethod(RiskBean.class, "secureMethod");

  • Set blacklist
// 必须将该选项设置为 true
QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
// 这里不区分静态方法与成员方法, 写法一致
// 不支持重载, riskMethod 的所有重载方法都会被禁止
QLExpressRunStrategy.addSecurityRiskMethod(RiskBean.class, "riskMethod");

The blacklists currently added by QLExpess by default include:

java.lang.System.exit
java.lang.Runtime.exec
java.lang.ProcessBuilder.start
java.lang.reflect.Method.invoke
java.lang.reflect.Class.forName
java.lang.reflect.ClassLoader.loadClass
java.lang.reflect.ClassLoader.findClass
  • Prevent endless loops
//可通过timeoutMillis参数设置脚本的运行超时时间:1000ms
Object r = runner.execute(express, context, null, true, false, 1000);

JEXL

  • Use sandbox
// 使用中应该通过JexlSandbox的重载构造方法进行配置
new JexlBuilder().sandbox(new JexlSandbox()).create();

  • Set whitelist permissions
new JexlBuilder().permissions(JexlPermissions.RESTRICTED.compose("com.jd.*")).create();

  • Feature switch
// 关闭循环、new 实例,import等特性
new JexlBuilder().features(new JexlFeatures().loops(false).newInstance(false).importPragma(false)).create();

3.5 Use cases

From industry usage, we can learn about the feasibility, ecology and integration of different expression engines, as well as best practices, and then learn from them. As you can see from the table below, AviatorScript, MVEL, and QLExpress all have use cases in domestic business lines. Some companies also have article output, which we can learn from.

name Case
AviatorScript liteflow, JD Starlink
MVEL easy-rules, compileflow, JD Starlink
OGNL MyBatis,Struts
Game Spring
QLExpress compileflow, liteflow, Alibaba’s internal business line
JEXL cat,Jelly
JEWEL JSP
Janino Apache Spark、Apache Flink、Groovy

3.6 Grammar

Syntax that is easy to understand and use can improve development efficiency and reduce learning costs. Next, we will compare the syntax design of different expression engines from the aspects of types, operators, control statements, collections, and method definitions.

In terms of types, AviatorScript has designed a unique type. When using it, you need to pay attention to its type conversion priority long->bigint->decimal->double. AviatorScript, MVEL, OGNL, and JEXL all support BigInteger and BigDecimal literals, which means that literals can be used for precise calculations, which is more convenient. For example, it 10.24Brepresents a BigDecimal literal (the suffix of BigDecimal literal in AviatorScript is M). In addition, AviatorScript and QLExpress also support high-precision calculation settings.

In terms of operators, QLExpress supports replacement, custom operators and adding operator aliases, which may help simplify complex expressions or make expressions more intuitive, but adding preset functions should achieve similar results. AviatorScript also supports custom partial operators, but the number of supports is quite limited. AviatorScript, SpEl, and JEXL support regular matching operators.

In terms of control statements, except for OGNL, SpEl, and JUEL, which do not support control statements, all others support it. However, it should be noted that the else ifsyntax of AviatorScript is somewhat special elsif, and the foreach statement is also different from Java.

In terms of collections, all except JUEL provide quick definition methods, but the syntax is different.

In terms of function definition, SpEl and JUEL do not support it, OGNL supports pseudo-lambda definition, and others support function definition. QLExpress does not support defining lambdas.

Taken together, there are more or less differences with Java syntax. AviatorScript has designed some unique syntax of its own, and you need to be familiar with it before using it. QLExpress supports custom operators to make expressions look more intuitive. The syntax of MVEL and JEXL may be closer to Java, making it easier to accept. The syntax of OGNL, SpEl, and JUEL is simpler and does not support control statements and function definitions. Of course, some more complex problems can be solved by presetting some functions.

4 Suggestions for selection

In terms of community, SpEl is undoubtedly the most active. AviatorScript, QLExpress, and MVEL are very popular in China, and QLExpress is endorsed by Alibaba.

In terms of code size and dependencies, AviatorScript and MVEL have fewer dependencies, and the code size is also smaller.

In terms of performance, if you use an expression engine to perform literal arithmetic calculations or method calls, you can choose SpEl or MVEL. If you want better overall performance, you can choose AviatorScript.

In terms of security, if you want to customize security options, you can consider AviatorScript, QLExpress and JEXL.

In terms of use cases, AviatorScript, MVEL, and QLExpress all have actual use cases in China.

In terms of grammar, there may be some subjective factors, which are for reference only. I personally think that the grammar design of MVEL and JEXL will be easier to use.

Through the evaluation and analysis of the above aspects, we hope to help the team choose the Java expression engine that is most suitable for their project based on their own situation and preferences.

5 References

QLExpress: https://github.com/alibaba/QLExpress

AviatorScript: https://github.com/killme2008/aviatorscript

MVEL: https://github.com/mvel/mvel

OGNL: https://github.com/orphan-oss/ognl

SpEl: https://github.com/spring-projects/spring-framework

Janino: https://github.com/janino-compiler/janino

JUEL: https://github.com/beckchr/juel

JEXL: https://github.com/apache/commons-jexl

Fel: https://github.com/dbcxy/fast-el

ik-expression: https://code.google.com/archive/p/ik-expression/

JSEL: https://code.google.com/archive/p/lite/wikis/JSEL.wiki

JMH: https://www.cnblogs.com/wupeixuan/p/13091381.html

Author: Jingdong Technology Feng Hao

Source: JD Cloud Developer Community Please indicate the source when forwarding

Alibaba Cloud suffered a serious failure and all products were affected (restored). Tumblr cooled down the Russian operating system Aurora OS 5.0. New UI unveiled Delphi 12 & C++ Builder 12, RAD Studio 12. Many Internet companies urgently recruit Hongmeng programmers. UNIX time is about to enter the 1.7 billion era (already entered). Meituan recruits troops and plans to develop the Hongmeng system App. Amazon develops a Linux-based operating system to get rid of Android's dependence on .NET 8 on Linux. The independent size is reduced by 50%. FFmpeg 6.1 "Heaviside" is released
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4090830/blog/10142679