Spring 表示式語言 (SpEL)
您可以使用 Spring 表示式語言 編寫的表示式來配置許多 Spring Integration 元件。
在大多數情況下,#root 物件是 Message,它有兩個屬性(headers 和 payload),允許使用諸如 payload、payload.thing、headers['my.header'] 等表示式。
在某些情況下,還會提供額外的變數。例如,<int-http:inbound-gateway/> 提供了 #requestParams(來自 HTTP 請求的引數)和 #pathVariables(來自 URI 中路徑佔位符的值)。
對於所有 SpEL 表示式,BeanResolver 可用於引用應用程式上下文中的任何 bean,例如 @myBean.foo(payload)。此外,還提供了兩個 PropertyAccessor。MapAccessor 允許透過鍵訪問 Map 中的值,而 ReflectivePropertyAccessor 允許訪問欄位和符合 JavaBean 規範的屬性(透過 getter 和 setter)。這就是您訪問 Message 頭和 payload 屬性的方式。
SpEL 評估上下文自定義
從 Spring Integration 3.0 開始,您可以向框架使用的 SpEL 評估上下文新增額外的 PropertyAccessor 例項。框架提供了(只讀)JacksonPropertyAccessor,您可以使用它訪問 JsonNode 或 String 中的 JSON 欄位。如果您有特定需求,也可以建立自己的 PropertyAccessor。
提供了 JacksonIndexAccessor 實現,該實現知道如何使用 Jackson 的 ArrayNode API 從 JSON 陣列中讀取索引。支援以整數文字形式提供的索引,例如 myJsonArray[1]。還支援負索引,例如 myJsonArray[-1],它等同於 myJsonArray[myJsonArray.length - 1]。此外,對於任何超出範圍的索引,都返回 null(有關詳細資訊,請參閱 ArrayNode.get(int))。
此外,您可以新增自定義函式。自定義函式是在類上宣告的 static 方法。函式和屬性訪問器在整個框架中使用的任何 SpEL 表示式中都可用。
以下配置顯示瞭如何使用自定義屬性訪問器和函式直接配置 IntegrationEvaluationContextFactoryBean
<bean id="integrationEvaluationContext"
class="org.springframework.integration.config.IntegrationEvaluationContextFactoryBean">
<property name="propertyAccessors">
<util:map>
<entry key="things">
<bean class="things.MyCustomPropertyAccessor"/>
</entry>
</util:map>
</property>
<property name="functions">
<map>
<entry key="barcalc" value="#{T(things.MyFunctions).getMethod('calc', T(things.MyThing))}"/>
</map>
</property>
</bean>
從 6.4 版本開始,AbstractEvaluationContextFactoryBean 支援注入 IndexAccessor 例項。有關更多資訊,請參閱 AbstractEvaluationContextFactoryBean 方法的 Javadoc。
為了方便起見,Spring Integration 為屬性訪問器和函式都提供了名稱空間支援,如下文所述。框架會為您自動配置工廠 bean。
此工廠 bean 定義會覆蓋預設的 integrationEvaluationContext bean 定義。它將自定義訪問器和一個自定義函式新增到列表中,該列表還包括前面提到的標準訪問器。
請注意,自定義函式是靜態方法。在上面的示例中,自定義函式是一個名為 MyFunctions 的類上的靜態方法 calc,它接受一個型別為 MyThing 的單個引數。
假設您有一個 payload 型別為 MyThing 的 Message。進一步假設您需要執行一些操作,從 MyThing 建立一個名為 MyObject 的物件,然後在該物件上呼叫一個名為 calc 的自定義函式。
標準的屬性訪問器不知道如何從 MyThing 獲取 MyObject,因此您可以編寫和配置一個自定義屬性訪問器來執行此操作。因此,您的最終表示式可能是 "#barcalc(payload.myObject)"。
工廠 bean 還有另一個屬性 (typeLocator),它允許您自定義在 SpEL 評估期間使用的 TypeLocator。您可能需要在某些使用非標準 ClassLoader 的環境中這樣做。在以下示例中,SpEL 表示式始終使用 bean 工廠的類載入器
<bean id="integrationEvaluationContext"
class="org.springframework.integration.config.IntegrationEvaluationContextFactoryBean">
<property name="typeLocator">
<bean class="org.springframework.expression.spel.support.StandardTypeLocator">
<constructor-arg value="#{beanFactory.beanClassLoader}"/>
</bean>
</property>
</bean>
SpEL 函式
Spring Integration 提供了名稱空間支援,允許您建立 SpEL 自定義函式。您可以指定 <spel-function/> 元件,以便為整個框架使用的 EvaluationContext 提供自定義 SpEL 函式。您無需配置前面所示的工廠 bean,而是可以新增一個或多個這些元件,框架會自動將它們新增到預設的 integrationEvaluationContext 工廠 bean。
例如,假設您有一個有用的靜態方法來評估 XPath。以下示例顯示瞭如何建立自定義函式來使用該方法
<int:spel-function id="xpath"
class="com.something.test.XPathUtils" method="evaluate(java.lang.String, java.lang.Object)"/>
<int:transformer input-channel="in" output-channel="out"
expression="#xpath('//things/@mythings', payload)" />
鑑於前面的例子
-
ID 為
integrationEvaluationContext的預設IntegrationEvaluationContextFactoryBeanbean 已註冊到應用程式上下文。 -
<spel-function/>被解析並新增到integrationEvaluationContext的functionsMap中,作為以其id為鍵、靜態Method為值的 Map 條目。 -
integrationEvaluationContext工廠 bean 建立一個新的StandardEvaluationContext例項,並使用預設的PropertyAccessor例項、BeanResolver和自定義函式進行配置。 -
該
EvaluationContext例項被注入到ExpressionEvaluatingTransformerbean 中。
要透過 Java 配置提供 SpEL 函式,您可以為每個函式宣告一個 SpelFunctionFactoryBean bean。以下示例顯示瞭如何建立自定義函式
@Bean
public SpelFunctionFactoryBean xpath() {
return new SpelFunctionFactoryBean(XPathUtils.class, "evaluate");
}
在父上下文中宣告的 SpEL 函式在任何子上下文中也可用。每個上下文都有自己的 integrationEvaluationContext 工廠 bean 例項,因為每個上下文都需要不同的 BeanResolver,但函式宣告是繼承的,可以透過宣告同名的 SpEL 函式來覆蓋。 |
內建 SpEL 函式
Spring Integration 提供以下標準函式,它們在啟動時會自動註冊到應用程式上下文
-
#jsonPath:評估指定物件上的“jsonPath”。此函式呼叫JsonPathUtils.evaluate(…),它委託給 Jayway JsonPath 庫。以下列表顯示了一些使用示例<transformer expression="#jsonPath(payload, '$.store.book[0].author')"/> <filter expression="#jsonPath(payload,'$..book[2].isbn') matches '\d-\d{3}-\d{5}-\d'"/> <splitter expression="#jsonPath(payload, '$.store.book')"/> <router expression="#jsonPath(payload, headers.jsonPath)"> <mapping channel="output1" value="reference"/> <mapping channel="output2" value="fiction"/> </router>#jsonPath還支援第三個(可選)引數:一個com.jayway.jsonpath.Filter陣列,可以透過引用 bean 或 bean 方法(例如)提供。使用此功能需要 Jayway JsonPath 庫( json-path.jar)位於類路徑中。否則,#jsonPathSpEL 函式將不會註冊。有關 JSON 的更多資訊,請參閱 Transformer 中的“JSON 轉換器”。
-
#xpath:用於評估給定物件上的 xpath。有關 XML 和 XPath 的更多資訊,請參閱 XML 支援 - 處理 XML Payload。
屬性訪問器
Spring Integration 提供了名稱空間支援,允許您建立 SpEL 自定義 PropertyAccessor 實現。您可以使用 <spel-property-accessors/> 元件向整個框架使用的 EvaluationContext 提供自定義 PropertyAccessor 例項列表。無需配置前面所示的工廠 bean,您可以新增此元件,框架會自動將訪問器新增到預設的 integrationEvaluationContext 工廠 bean。此外,從 6.4 版本開始,提供了一個專門的 <index-accessors> 子元素來以類似方式配置 IndexAccessor bean。以下示例顯示瞭如何操作
<int:spel-property-accessors>
<index-accessors>
<beans:bean id="jsonIndex" class="org.springframework.integration.json.JacksonIndexAccessor"/>
</index-accessors>
<bean id="jsonPA" class="org.springframework.integration.json.JacksonPropertyAccessor"/>
<ref bean="fooPropertyAccessor"/>
</int:spel-property-accessors>
在前面的示例中,兩個自定義 PropertyAccessor 例項被注入到 EvaluationContext 中(按照它們宣告的順序)。
要透過 Java 配置提供 PropertyAccessor 例項,您應該宣告一個名為 spelPropertyAccessorRegistrar 的 SpelPropertyAccessorRegistrar bean(由 IntegrationContextUtils.SPEL_PROPERTY_ACCESSOR_REGISTRAR_BEAN_NAME 常量指定)。以下示例顯示瞭如何使用 Java 配置兩個自定義 PropertyAccessor(從 6.4 版本開始還包括 IndexAccessor)例項
@Bean
public SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
return new SpelPropertyAccessorRegistrar(new JacksonPropertyAccessor())
.add(fooPropertyAccessor())
.add(new JacksonIndexAccessor());
}
|
在父上下文中宣告的自定義
|