此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
属性、数组、列表、映射和索引器
Spring 表达式语言支持导航对象图和索引 融入各种结构。
数值索引值从零开始,例如在访问 nth元素 Java 中的数组。 |
有关如何导航对象图和索引到各种结构中的详细信息,请参阅 Safe Navigation Operator 部分 使用 null 安全运算符。 |
属性导航
您可以使用句点来导航对象图中的属性引用,以指示
嵌套属性值。的Inventor
类pupin
和tesla
,是
填充了 Classes used in the examples 部分中列出的数据。自
在对象图中向下导航,获取 Tesla 的出生年份和 Pupin 的出生城市。
我们使用以下表达式:
-
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)
索引到 Map 中
通过在方括号内指定键值来获取映射的内容。在
以下示例中,由于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)
索引到对象
可以通过在 方括号。这类似于根据 map 的 key 访问 map 的值。这 以下示例演示了如何对对象进行索引以检索特定的 财产。
-
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 的 API 中。
为了支持常见的用例,Spring 提供了一个内置的ReflectiveIndexAccessor
哪
是灵活的IndexAccessor
使用反射读取和选择性写入
目标对象的索引结构。索引结构可以通过public
read-method(读取时)或public
write-method(写入时)。
read-method 和 write-method 之间的关系基于一个约定:
适用于索引结构的典型实现。
ReflectiveIndexAccessor 还实现了CompilableIndexAccessor 为了
支持编译为字节码以进行读取访问。但是请注意,配置的 read-method 必须是
invokable 通过public class 或public interface 进行编译。 |
以下代码清单定义了一个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")
.使用该访问器
registered 和FruitMap
注册为名为#fruitMap
、SPEL
表达#fruitMap[T(example.Color).RED]
将评估为"cherry"
.
读写IndexAccessor
为FruitMap
可以通过以下方式创建new
ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit", "setFruit")
.有了那个
registeror 已注册,并且FruitMap
注册为名为#fruitMap
、SPEL
表达#fruitMap[T(example.Color).RED] = 'strawberry'
可用于更改
颜色 red from 的水果映射"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)