Spring 表达式语言 (SpEL)
您可以使用 Spring 表达式语言 编写的表达式来配置许多 Spring 集成组件。
在大多数情况下,#root
对象是 Message
,它有两个属性(headers
和 payload
),允许使用诸如 payload
、payload.thing
、headers['my.header']
等等的表达式。
在某些情况下,会提供其他变量。例如,<int-http:inbound-gateway/>
提供 #requestParams
(来自 HTTP 请求的参数)和 #pathVariables
(来自 URI 中路径占位符的值)。
对于所有 SpEL 表达式,都提供了一个 BeanResolver
来启用对应用程序上下文中的任何 bean 的引用(例如,@myBean.foo(payload)
)。此外,还提供了两个 PropertyAccessors
。MapAccessor
允许使用键访问 Map
中的值,而 ReflectivePropertyAccessor
允许访问字段和符合 JavaBean 规范的属性(使用 getter 和 setter)。这就是您可以访问 Message
的标头和有效负载属性的方式。
SpEL 评估上下文定制
从 Spring Integration 3.0 开始,您可以将其他 PropertyAccessor
实例添加到框架使用的 SpEL 评估上下文中。框架提供了(只读)JsonPropertyAccessor
,您可以使用它来访问 JsonNode
或 String
中的 JSON 的字段。如果您有特殊需求,也可以创建自己的 PropertyAccessor
。
此外,您可以添加自定义函数。自定义函数是在类上声明的 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>
为了方便起见,Spring Integration 为属性访问器和函数都提供了命名空间支持,如以下部分所述。框架会自动为您配置工厂 bean。
此工厂 bean 定义覆盖了默认的 integrationEvaluationContext
bean 定义。它将自定义访问器和一个自定义函数添加到列表中(其中还包括前面提到的标准访问器)。
请注意,自定义函数是静态方法。在前面的示例中,自定义函数是一个名为 calc
的静态方法,它位于名为 MyFunctions
的类中,并接受一个类型为 MyThing
的参数。
假设您有一个 Message
,其有效负载的类型为 MyThing
。此外,假设您需要执行一些操作来从 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/>
组件来提供 自定义 SpEL 函数 到整个框架中使用的 EvaluationContext
。无需配置前面显示的工厂 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)" />
鉴于前面的示例
-
默认的
IntegrationEvaluationContextFactoryBean
Bean(ID 为integrationEvaluationContext
)已注册到应用程序上下文。 -
<spel-function/>
被解析并添加到integrationEvaluationContext
的functions
Map
中,作为具有其id
作为键和静态Method
作为值的映射条目。 -
integrationEvaluationContext
工厂 Bean 创建一个新的StandardEvaluationContext
实例,并使用默认的PropertyAccessor
实例、BeanResolver
和自定义函数进行配置。 -
该
EvaluationContext
实例被注入到ExpressionEvaluatingTransformer
Bean 中。
要使用 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
) 位于类路径中。否则,#jsonPath
SpEL 函数不会注册。有关 JSON 的更多信息,请参阅 Transformer 中的“JSON 变换器”。
-
#xpath
:在某些提供的对象上评估 xpath。有关 XML 和 XPath 的更多信息,请参阅 XML 支持 - 处理 XML 负载。
属性访问器
Spring Integration 提供命名空间支持,让您创建 SpEL 自定义 PropertyAccessor
实现。您可以使用 <spel-property-accessors/>
组件为整个框架使用的 EvaluationContext
提供自定义 PropertyAccessor
实例列表。您可以添加一个或多个这些组件,而不是配置前面显示的工厂 Bean,框架会自动将访问器添加到默认的 integrationEvaluationContext
工厂 Bean 中。以下示例展示了如何执行此操作
<int:spel-property-accessors>
<bean id="jsonPA" class="org.springframework.integration.json.JsonPropertyAccessor"/>
<ref bean="fooPropertyAccessor"/>
</int:spel-property-accessors>
在前面的示例中,两个自定义的 PropertyAccessor
实例被注入到 EvaluationContext
中(按照它们声明的顺序)。
要使用 Java 配置提供 PropertyAccessor
实例,您应该声明一个名为 spelPropertyAccessorRegistrar
的 SpelPropertyAccessorRegistrar
bean(由 IntegrationContextUtils.SPEL_PROPERTY_ACCESSOR_REGISTRAR_BEAN_NAME
常量决定)。以下示例展示了如何使用 Java 配置两个自定义的 PropertyAccessor
实例
@Bean
public SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
return new SpelPropertyAccessorRegistrar(new JsonPropertyAccessor())
.add(fooPropertyAccessor());
}
在父上下文声明的自定义
|