此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
属性、数组、列表、映射和索引器
Spring 表达式语言支持导航对象图和索引 进入各种结构。
数值索引值从零开始,例如当访问 nth元素的 Java 中的数组。 |
有关如何导航对象图和索引到各种结构中的详细信息,请参阅安全导航运算符部分 使用空安全运算符。 |
属性导航
您可以使用句点来指示对象图中的属性引用
嵌套属性值。的实例Inventor
类pupin
和tesla
,是
填充了示例中使用的类部分中列出的数据。自
向下导航对象图,获取特斯拉的出生年份和普平的出生城市,
我们使用以下表达式:
-
Java
-
Kotlin
// evaluates to 1856
int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(context);
// evaluates to "Smiljan"
String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
// evaluates to 1856
val year = parser.parseExpression("birthdate.year + 1900").getValue(context) as Int
// evaluates to "Smiljan"
val city = parser.parseExpression("placeOfBirth.city").getValue(context) as String
允许对属性名称的第一个字母不区分大小写。因此,
上面示例中的表达式可以写成 |
索引数组和集合
这 nth数组或集合的元素(例如,一个Set
或List
) 可以是
使用方括号表示法获得,如下例所示。
如果索引集合是 对于任何其他类型的 |
-
Java
-
Kotlin
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// Inventions Array
// evaluates to "Induction motor"
String invention = parser.parseExpression("inventions[3]").getValue(
context, tesla, String.class);
// Members List
// evaluates to "Nikola Tesla"
String name = parser.parseExpression("members[0].name").getValue(
context, ieee, String.class);
// List and Array Indexing
// evaluates to "Wireless communication"
String invention = parser.parseExpression("members[0].inventions[6]").getValue(
context, ieee, String.class);
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
// Inventions Array
// evaluates to "Induction motor"
val invention = parser.parseExpression("inventions[3]").getValue(
context, tesla, String::class.java)
// Members List
// evaluates to "Nikola Tesla"
val name = parser.parseExpression("members[0].name").getValue(
context, ieee, String::class.java)
// List and Array Indexing
// evaluates to "Wireless communication"
val invention = parser.parseExpression("members[0].inventions[6]").getValue(
context, ieee, String::class.java)
索引到字符串中
这 nth字符串的字符可以通过指定 square 内的索引来获得 括号,如以下示例所示。
这 nth字符串的字符将计算为java.lang.String ,而不是java.lang.Character . |
-
Java
-
Kotlin
// evaluates to "T" (8th letter of "Nikola Tesla")
String character = parser.parseExpression("members[0].name[7]")
.getValue(societyContext, String.class);
// evaluates to "T" (8th letter of "Nikola Tesla")
val character = parser.parseExpression("members[0].name[7]")
.getValue(societyContext, String::class.java)
索引到地图中
映射的内容是通过指定方括号内的键值来获取的。在
以下示例,因为officers
map 是字符串,我们可以指定
字符串文字,例如'president'
:
-
Java
-
Kotlin
// Officer's Map
// evaluates to Inventor("Pupin")
Inventor pupin = parser.parseExpression("officers['president']")
.getValue(societyContext, Inventor.class);
// evaluates to "Idvor"
String city = parser.parseExpression("officers['president'].placeOfBirth.city")
.getValue(societyContext, String.class);
String countryExpression = "officers['advisors'][0].placeOfBirth.country";
// setting values
parser.parseExpression(countryExpression)
.setValue(societyContext, "Croatia");
// evaluates to "Croatia"
String country = parser.parseExpression(countryExpression)
.getValue(societyContext, String.class);
// Officer's Map
// evaluates to Inventor("Pupin")
val pupin = parser.parseExpression("officers['president']")
.getValue(societyContext, Inventor::class.java)
// evaluates to "Idvor"
val city = parser.parseExpression("officers['president'].placeOfBirth.city")
.getValue(societyContext, String::class.java)
val countryExpression = "officers['advisors'][0].placeOfBirth.country"
// setting values
parser.parseExpression(countryExpression)
.setValue(societyContext, "Croatia")
// evaluates to "Croatia"
val country = parser.parseExpression(countryExpression)
.getValue(societyContext, String::class.java)
索引到对象
可以通过在方括号中指定属性名称来获取对象的属性。这类似于根据映射的键访问映射的值。 这 以下示例演示了如何索引到对象中以检索特定的 财产。
-
Java
-
Kotlin
// Create an inventor to use as the root context object.
Inventor tesla = new Inventor("Nikola Tesla");
// evaluates to "Nikola Tesla"
String name = parser.parseExpression("#root['name']")
.getValue(context, tesla, String.class);
// Create an inventor to use as the root context object.
val tesla = Inventor("Nikola Tesla")
// evaluates to "Nikola Tesla"
val name = parser.parseExpression("#root['name']")
.getValue(context, tesla, String::class.java)
索引到自定义结构中
从 Spring Framework 6.2 开始,Spring 表达式语言支持索引到自定义结构中,允许开发人员实现和注册IndexAccessor
使用EvaluationContext
. 如果您想支持编译依赖于自定义索引访问器的表达式,则该索引访问器必须实现CompilableIndexAccessor
SPI.
为了支持常见用例,Spring 提供了一个内置的ReflectiveIndexAccessor
哪 是一种灵活的IndexAccessor
使用反射读取和可选地写入目标对象的索引结构。索引结构可以通过public
read-方法(读取时)或public
write-method(写入时)。read-method 和 write-method 之间的关系基于一个约定,即适用于索引结构的典型实现。
ReflectiveIndexAccessor 还实现CompilableIndexAccessor 以便支持编译为字节码以进行读取访问。但是请注意,配置的读取方法必须是可通过public class 或public 用于编译成功的接口。 |
以下代码列表定义了Color
enum 和FruitMap
类型,其行为类似于map,但不实现java.util.Map
接口。 因此,如果您想索引到 一个FruitMap
在 SpEL 表达式中,您需要注册一个IndexAccessor
.
public enum Color {
RED, ORANGE, YELLOW
}
public class FruitMap {
private final Map<Color, String> map = new HashMap<>();
public FruitMap() {
this.map.put(Color.RED, "cherry");
this.map.put(Color.ORANGE, "orange");
this.map.put(Color.YELLOW, "banana");
}
public String getFruit(Color color) {
return this.map.get(color);
}
public void setFruit(Color color, String fruit) {
this.map.put(color, fruit);
}
}
只读IndexAccessor
为FruitMap
可以通过new
ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit")
. 使用该访问器已注册和FruitMap
注册为名为#fruitMap
、SpEL 表达#fruitMap[T(example.Color).RED]
将评估为"cherry"
.
读写IndexAccessor
为FruitMap
可以通过new
ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit", "setFruit")
. 有了访问器注册,并且FruitMap
注册为名为#fruitMap
、SpEL 表达#fruitMap[T(example.Color).RED] = 'strawberry'
可用于更改fruit mapping 的红色从"cherry"
自"strawberry"
.
以下示例演示了如何注册ReflectiveIndexAccessor
索引转换为FruitMap
,然后索引到FruitMap
在 SpEL 表达式中。
-
Java
-
Kotlin
// Create a ReflectiveIndexAccessor for FruitMap
IndexAccessor fruitMapAccessor = new ReflectiveIndexAccessor(
FruitMap.class, Color.class, "getFruit", "setFruit");
// Register the IndexAccessor for FruitMap
context.addIndexAccessor(fruitMapAccessor);
// Register the fruitMap variable
context.setVariable("fruitMap", new FruitMap());
// evaluates to "cherry"
String fruit = parser.parseExpression("#fruitMap[T(example.Color).RED]")
.getValue(context, String.class);
// Create a ReflectiveIndexAccessor for FruitMap
val fruitMapAccessor = ReflectiveIndexAccessor(
FruitMap::class.java, Color::class.java, "getFruit", "setFruit")
// Register the IndexAccessor for FruitMap
context.addIndexAccessor(fruitMapAccessor)
// Register the fruitMap variable
context.setVariable("fruitMap", FruitMap())
// evaluates to "cherry"
val fruit = parser.parseExpression("#fruitMap[T(example.Color).RED]")
.getValue(context, String::class.java)