|
如需使用最新稳定版本,请使用 Spring Integration 7.0.4! |
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))。
此外,还有两个 PropertyAccessors 可用。
MapAccessor 允许通过使用键和 Map 来访问 ReflectivePropertyAccessor 中的值,后者支持通过 getter 和 setter 方法访问字段和符合 JavaBean 规范的属性。
这就是访问 Message 头部和负载属性的方式。
SpEL 评估上下文自定义
从 Spring Integration 3.0 开始,您可以向框架使用的 SpEL 评估上下文添加额外的 PropertyAccessor 实例。
框架提供了(只读的)JsonPropertyAccessor,您可以使用它来访问 JsonNode 或 String 中的字段或 JSON。
如果您有特定需求,也可以创建自己的 PropertyAccessor。
从版本 6.4 开始,提供了 JsonIndexAccessor 实现,它能够使用 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 方法的 Javadocs。
为了方便起见,Spring Integration 为属性访问器和函数提供了命名空间支持,如下文所述。 该框架会自动为您配置工厂 Bean。
此工厂 bean 定义覆盖了默认的 integrationEvaluationContext bean 定义。
它将自定义访问器和一个自定义函数添加到列表中(该列表还包括之前提到的标准访问器 mentioned earlier)。
请注意,自定义函数是静态方法。
在前面的示例中,该自定义函数是一个名为 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/> 组件,为整个框架中使用的 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)" />
鉴于上述示例:
-
默认值为
IntegrationEvaluationContextFactoryBean且 ID 为integrationEvaluationContext的 bean 已注册到应用上下文中。 -
The
<spel-function/>被解析并添加到functionsMap中作为映射条目,其id作为键,静态Method作为值。 -
The
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)。 否则,#jsonPathSpEL 函数将不会被注册。有关 JSON 的更多信息,请参阅 转换器 中的'JSON 转换器'。
-
#xpath: 对某个提供的对象求值 xpath。 有关 XML 和 XPath 的更多信息,请参见 XML 支持 - 处理 XML 负载。
属性访问器
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.JsonIndexAccessor"/>
</index-accessors>
<bean id="jsonPA" class="org.springframework.integration.json.JsonPropertyAccessor"/>
<ref bean="fooPropertyAccessor"/>
</int:spel-property-accessors>
在前面的示例中,两个自定义 PropertyAccessor 实例被注入到 EvaluationContext 中(按照它们声明的顺序)。
要使用 Java Configuration 提供 PropertyAccessor 个实例,您应当声明一个名称为 spelPropertyAccessorRegistrar(由 IntegrationContextUtils.SPEL_PROPERTY_ACCESSOR_REGISTRAR_BEAN_NAME 常量决定)的 SpelPropertyAccessorRegistrar Bean。
以下示例展示了如何使用 Java 配置两个自定义 PropertyAccessor(从版本 6.4 起支持 IndexAccessor)实例:
@Bean
public SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
return new SpelPropertyAccessorRegistrar(new JsonPropertyAccessor())
.add(fooPropertyAccessor())
.add(new JsonIndexAccessor());
}
|
在父上下文中声明的自定义
|