| 注释 | 使用 ## 或 // 指定,并延伸到行尾,例如 ## 这是一个注释 或 // 这是一个注释 多行注释使用 /*...*/,例如 /* 这是一个多行注释 */ |
| 标识符 / 变量 | 必须以 a-z、A-Z、_ 或 $ 开头。之后可以跟随 0-9、a-z、A-Z、_ 或 $。例如:有效: var1、_a99、$1 无效: 9v、!a99、1$ 变量名区分大小写,例如 var1 和 Var1 是不同的变量。注意: 脚本中 不支持带有连字符的变量,例如 commons-logging // 无效的变量名(带连字符) 被视为从变量 commons 中减去 logging,而不是有效变量。脚本中也支持 ant-style 变量,以下是有效的变量名:my.dotted.var 注: 以下关键字是保留的,不能作为变量名或属性使用点操作符:or、and、eq、ne、lt、gt、le、ge、div、mod、not、null、true、false、new、var、do、while、break、continue、function、return。例如:以下是无效的:my.new.dotted.var // 无效('new' 是关键字) 在这种情况下,可以使用带引号的标识符或 [ ] 操作符,例如:my.'new'.dotted.var 或 my['new'].dotted.var |
| 脚本 | 脚本由零个或多个语句组成,通常包含在一个函数定义块中。脚本可以包括一个或多个 pragma。脚本可以从字符串、文件或 URL 读取。脚本可以创建具有命名参数的函数,这允许后续评估时使用参数。默认情况下,在没有显式 return 语句的情况下,脚本返回最后一个被评估的语句的值。使用 return 关键字,脚本将返回跟随的表达式(或 null)。 |
| #pragma | 声明一个 pragma,是一种将信息从脚本传达给执行环境的方法。例如 #pragma execution.option 42 将声明一个名为 execution.option 的 pragma,值为 42。Pragma 键可以是标识符或 antish 名称,pragma 值可以是文字(布尔值、整数、实数、字符串、null、NaN)和 antish 名称。尽管 pragma 是语句,但它们在运行时不会被评估;它们是与脚本解析后相关联的常量。用户代码期望从脚本中访问 pragma 映射以更改一些函数行为。有 3 个内置 pragma:jexl.options 使用选项标志语法覆盖评估选项。#pragma jexl.options "+strict -safe +lexical +lexicalShade" 将让脚本以严格模式运行,安全模式为假,词法作用域为真,词法阴影为真。jexl.namespace.*ns_prefix* 声明一个在脚本执行生命周期内有效的命名空间,值为完全限定的命名空间类名。#pragma jexl.namespace.str java.lang.String 将 'str' 声明为使用 String 类的命名空间。jexl.import 与 'new' 操作符配合使用。它声明 new ClassIdentifier(...) 将访问的包 - 按声明顺序 - 以将类名解析为完全限定的类名。#pragma jexl.import java.net 将允许执行 let url = new URL("https://commons.apache.org");,URL 类名被解析为 java.net.URL 完全限定类名。 |
| 语句 | 语句可以是空语句、分号(;)、块、条件、变量声明或表达式。语句可以选择性地以分号终止。单个语句或语句块可以被注释。 |
| 块 | 块是指用大括号({, })包围的多个语句。 |
| 局部变量 | 可以使用 let、const 和 var 关键字定义,其标识规则与上下文变量相同。let 声明一个具有词法块作用域的局部变量(或参数)。该变量只能在其定义块及任何嵌套的子块中访问。这还禁止在该作用域内重新声明变量。注意:这模仿了 Java 行为,与 ECMAScript 不同。const 的行为与 let 类似,但会阻止变量被任何副作用操作符重新分配。var 声明一个作用域为整个脚本的变量,并允许重新定义。基本声明:let x; 带赋值的声明:const theAnswer = 42; 无效声明:var x.y; 局部变量在解析时优先于 上下文变量。当脚本使用命名参数创建时,这些参数的行为也像局部变量一样。局部变量不能使用 ant-style 命名,只能使用一个标识符。 |
| 表达式 | 表达式可以是文字、变量、赋值、访问操作符、函数定义、函数调用、方法调用或求值操作符。 |
| 赋值 | 给变量(my.var = 'a value')赋值。 |
| 函数定义 | 在脚本中定义一个函数,通常与局部变量赋值相关联。var fun = function(x, y) { x + y } 还支持以下语法:var fun = (x, y) -> { x + y } var fun = (let x, let y) -> { x + y } const fun = (const x, const y) -> { x + y } function fun(const x, const y) { x + y } 如果函数只有一个参数,则可以省略圆括号 var fun = x -> { x * x }。函数的主体为表达式时,可以省略花括号,如:var fun = x -> x * x。注意,函数可以使用其定义脚本中的局部变量和参数。那些变量的值在定义时绑定到函数环境中。var t = 20; var s = function(x, y) {x + y + t}; t = 54; s(15, 7) 函数闭包在定义时捕获 't';评估结果将导致 15 + 7 + 20 = 42。 |
| 函数调用 | 调用函数遵循常规约定,例如 fun(17, 25) 将使用参数 17 和 25 调用 fun 函数。 |
| 方法调用 | 调用对象的方法,例如 "hello world".hashCode() 将调用 "hello world" 字符串的 hashCode 方法。在多个参数和重载的情况下,JEXL 将尽力找到最合适的、没有歧义的方法调用。 |
| 访问操作符 | 允许通过使用方括号或点符号来评估对象的属性、集合的值或数组中的元素,例如 foo.bar 将访问 foo 对象的 bar 属性。arr1[0] 将访问 arr1 数组的第一个元素。安全访问操作符 foo?.bar 会在导航路径上的任何 null 或不存在的引用时快捷处理,从而允许无错误的安全导航。在前面的表达式中,如果 foo 为 null,则整个表达式将评估为 null。这是防御性表达式的有效快捷方式,例如 x?.y?.z,否则将表达为 x? (x.y? (x.y.z ?: null) :null) : null。安全访问数组操作符(如 foo?[bar])提供与安全访问操作符相同的行为,并在导航路径上的任何 null 或不存在的引用时快捷处理,从而允许无错误的安全导航。注意,这也可以链式使用,如 x?[y]?[z]。访问操作符可以在 JexlArithmetic 中被重载,因此操作符的行为会根据操作符参数的类型而有所不同。 |
| 求值操作符 | 执行一个、两个或三个参数值的计算、逻辑或比较操作,这些值是表达式,例如 40 + 2 将调用两个整数文字之间的 add 操作符。 |
| @注解 | 它们允许将语句的执行包装在提供的调用者中;典型示例包括:@synchronized(x) x.someMethod(); 注解可以用零个或多个参数声明;@lenient x.someMethod(); @synchronized(x) x.someMethod(); @parallel(pool, 8) x.someMethod(); 也可以链式声明,如:@lenient @silent x.someMethod(); |