屬性、陣列、列表、映射和索引器
Spring 運算式語言提供導覽物件圖形和索引到各種結構中的支援。
數值索引值從零開始,例如在 Java 中存取陣列的第 n個元素時。 |
請參閱 安全導航運算子 章節,以了解如何使用空值安全運算子導覽物件圖形並索引到各種結構中。 |
屬性導航
您可以使用句點導覽物件圖形內的屬性參考,以指示巢狀屬性值。Inventor
類別的實例 pupin
和 tesla
已使用 範例中使用的類別 章節中列出的資料填入。若要向下導覽物件圖形並取得 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
屬性名稱的第一個字母允許不區分大小寫。因此,上述範例中的運算式可以寫為 |
索引到陣列和集合中
可以使用方括號表示法取得陣列或集合(例如,Set
或 List
)的第 n個元素,如下列範例所示。
如果索引集合是 對於任何其他類型的 |
-
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)
索引到字串中
可以透過在方括號內指定索引來取得字串的第 n個字元,如下列範例所示。
字串的第 n個字元將評估為 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
映射的鍵是字串,因此我們可以指定字串常值,例如 '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 運算式語言支援索引到自訂結構中,允許開發人員使用 EvaluationContext
實作和註冊 IndexAccessor
。如果您想要支援依賴自訂索引存取子的運算式的編譯,則該索引存取子必須實作 CompilableIndexAccessor
SPI。
為了支援常見的使用案例,Spring 提供內建的 ReflectiveIndexAccessor
,這是一個彈性的 IndexAccessor
,它使用反射從目標物件的索引結構讀取和選擇性地寫入。可以透過 public
讀取方法(讀取時)或 public
寫入方法(寫入時)存取索引結構。讀取方法和寫入方法之間的關係基於適用於索引結構典型實作的慣例。
ReflectiveIndexAccessor 也實作 CompilableIndexAccessor ,以支援 編譯 為位元組碼以進行讀取存取。但是請注意,組態的讀取方法必須可透過 public 類別或 public 介面調用,編譯才能成功。 |
以下程式碼清單定義了 Color
列舉和 FruitMap
類型,其行為類似於映射,但不實作 java.util.Map
介面。因此,如果您想要在 SpEL 運算式中索引到 FruitMap
,則需要註冊 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);
}
}
可以透過 new ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit")
建立 FruitMap
的唯讀 IndexAccessor
。在註冊該存取子並將 FruitMap
註冊為名為 #fruitMap
的變數後,SpEL 運算式 #fruitMap[T(example.Color).RED]
將評估為 "cherry"
。
可以透過 new ReflectiveIndexAccessor(FruitMap.class, Color.class, "getFruit", "setFruit")
建立 FruitMap
的讀寫 IndexAccessor
。在註冊該存取子並將 FruitMap
註冊為名為 #fruitMap
的變數後,SpEL 運算式 #fruitMap[T(example.Color).RED] = 'strawberry'
可用於將紅色水果映射從 "cherry"
變更為 "strawberry"
。
以下範例示範如何註冊 ReflectiveIndexAccessor
以索引到 FruitMap
中,然後在 SpEL 運算式中索引到 FruitMap
中。
-
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)