如需使用最新稳定版本,请使用 Spring Integration 7.0.4spring-doc.cadn.net.cn

Spring 表达式语言(SpEL)

您可以通过使用用 Spring 表达式语言 编写的表达式来配置许多 Spring Integration 组件。spring-doc.cadn.net.cn

在大多数情况下,#root对象是Message,它具有两个属性(headerspayload),允许执行如payloadpayload.thingheaders['my.header']等表达式。spring-doc.cadn.net.cn

在某些情况下,会提供额外的变量。 例如,<int-http:inbound-gateway/> 提供 #requestParams(来自 HTTP 请求的参数)和 #pathVariables(来自 URI 中路径占位符的值)。spring-doc.cadn.net.cn

对于所有 SpEL 表达式,BeanResolver 可用于引用应用程序上下文中的任何 Bean(例如 @myBean.foo(payload))。 此外,还有两个 PropertyAccessors 可用。 MapAccessor 允许通过使用键和 Map 来访问 ReflectivePropertyAccessor 中的值,后者支持通过 getter 和 setter 方法访问字段和符合 JavaBean 规范的属性。 这就是访问 Message 头部和负载属性的方式。spring-doc.cadn.net.cn

SpEL 评估上下文自定义

从 Spring Integration 3.0 开始,您可以向框架使用的 SpEL 评估上下文添加额外的 PropertyAccessor 实例。 框架提供了(只读的)JsonPropertyAccessor,您可以使用它来访问 JsonNodeString 中的字段或 JSON。 如果您有特定需求,也可以创建自己的 PropertyAccessorspring-doc.cadn.net.cn

从版本 6.4 开始,提供了 JsonIndexAccessor 实现,它能够使用 Jackson 的 ArrayNode API 读取 JSON 数组中的索引。 支持以整数字面量形式提供的索引,例如 myJsonArray[1]。 还支持负数索引,例如 myJsonArray[-1],其等价于 myJsonArray[myJsonArray.length - 1]。 此外,对于任何超出边界的索引,将返回 null(详细信息请参见 ArrayNode.get(int))。spring-doc.cadn.net.cn

此外,您还可以添加自定义函数。 自定义函数是在类上声明的 static 方法。 函数和属性访问器可在框架中使用的任何 SpEL 表达式中调用。spring-doc.cadn.net.cn

以下配置展示了如何使用自定义属性访问器和函数直接配置 IntegrationEvaluationContextFactoryBeanspring-doc.cadn.net.cn

<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-doc.cadn.net.cn

为了方便起见,Spring Integration 为属性访问器和函数提供了命名空间支持,如下文所述。 该框架会自动为您配置工厂 Bean。spring-doc.cadn.net.cn

此工厂 bean 定义覆盖了默认的 integrationEvaluationContext bean 定义。 它将自定义访问器和一个自定义函数添加到列表中(该列表还包括之前提到的标准访问器 mentioned earlier)。spring-doc.cadn.net.cn

请注意,自定义函数是静态方法。 在前面的示例中,该自定义函数是一个名为 calc 的静态方法,属于名为 MyFunctions 的类,并接收一个类型为 MyThing 的单个参数。spring-doc.cadn.net.cn

假设您有一个 Message,其负载的类型为 MyThing。 此外,假设您需要执行某些操作以从 MyThing 创建一个名为 MyObject 的对象,然后在该对象上调用一个名为 calc 的自定义函数。spring-doc.cadn.net.cn

标准属性访问器不知道如何从 MyThing 获取 MyObject,因此你可以编写并配置一个自定义的属性访问器来实现这一功能。 最终你的表达式可能是 "#barcalc(payload.myObject)"spring-doc.cadn.net.cn

工厂 bean 还有另一个属性(typeLocator),允许您自定义 SpEL 求值过程中使用的 TypeLocator。 在某些使用非标准 ClassLoader 的环境中运行时,您可能需要这样做。 在以下示例中,SpEL 表达式始终使用该 bean 工厂的类加载器:spring-doc.cadn.net.cn

<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 中。spring-doc.cadn.net.cn

例如,假设您有一个用于评估 XPath 的实用静态方法。 以下示例展示了如何创建自定义函数以使用该方法的:spring-doc.cadn.net.cn

<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)" />

鉴于上述示例:spring-doc.cadn.net.cn

  • 默认值为 IntegrationEvaluationContextFactoryBean 且 ID 为 integrationEvaluationContext 的 bean 已注册到应用上下文中。spring-doc.cadn.net.cn

  • The <spel-function/> 被解析并添加到 functions Map 中作为映射条目,其 id 作为键,静态 Method 作为值。spring-doc.cadn.net.cn

  • The integrationEvaluationContext 工厂 Bean 创建一个新 StandardEvaluationContext 实例,并使用默认的 PropertyAccessor 实例、BeanResolver 以及自定义函数进行配置。spring-doc.cadn.net.cn

  • EvaluationContext 实例被注入到 ExpressionEvaluatingTransformer 的 Bean 中。spring-doc.cadn.net.cn

若要使用 Java 配置提供 SpEL 函数,您可以为每个函数声明一个 SpelFunctionFactoryBean bean。 以下示例展示了如何创建自定义函数:spring-doc.cadn.net.cn

@Bean
public SpelFunctionFactoryBean xpath() {
    return new SpelFunctionFactoryBean(XPathUtils.class, "evaluate");
}
在父上下文中声明的 SpEL 函数也会在任何子上下文中可用。 每个上下文都有自己的 integrationEvaluationContext 工厂 bean 实例,因为每个都需要不同的 BeanResolver,但函数声明会被继承,并且可以通过声明同名 SpEL 函数进行覆盖。

内置 SpEL 函数

Spring Integration 提供以下标准功能,这些功能在启动时会自动注册到应用程序上下文中:spring-doc.cadn.net.cn

  • #jsonPath: 在指定对象上评估'jsonPath'。 此函数调用 JsonPathUtils.evaluate(…​),后者委托给 Jayway JsonPath 库。 以下代码段展示了一些使用示例:spring-doc.cadn.net.cn

    <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 方法的引用来提供(例如)。spring-doc.cadn.net.cn

    使用此功能需要类路径中包含 Jayway JsonPath 库 (json-path.jar)。 否则,#jsonPath SpEL 函数将不会被注册。

    有关 JSON 的更多信息,请参阅 转换器 中的'JSON 转换器'。spring-doc.cadn.net.cn

  • #xpath: 对某个提供的对象求值 xpath。 有关 XML 和 XPath 的更多信息,请参见 XML 支持 - 处理 XML 负载spring-doc.cadn.net.cn

属性访问器

Spring Integration 提供命名空间支持,让您能够创建 SpEL 自定义 PropertyAccessor 实现。 您可以使用 <spel-property-accessors/> 组件向框架中使用的 EvaluationContext 提供一组自定义 PropertyAccessor 实例。 无需配置之前显示的工厂 Bean,只需添加此组件,框架便会自动将访问器添加到默认的 integrationEvaluationContext 工厂 Bean 中。 此外,从 6.4 版本开始,提供了一个专用的 <index-accessors> 子元素,以类似方式配置 IndexAccessor Bean。 以下示例展示了如何实现:spring-doc.cadn.net.cn

<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 中(按照它们声明的顺序)。spring-doc.cadn.net.cn

要使用 Java Configuration 提供 PropertyAccessor 个实例,您应当声明一个名称为 spelPropertyAccessorRegistrar(由 IntegrationContextUtils.SPEL_PROPERTY_ACCESSOR_REGISTRAR_BEAN_NAME 常量决定)的 SpelPropertyAccessorRegistrar Bean。 以下示例展示了如何使用 Java 配置两个自定义 PropertyAccessor(从版本 6.4 起支持 IndexAccessor)实例:spring-doc.cadn.net.cn

@Bean
public SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
    return new SpelPropertyAccessorRegistrar(new JsonPropertyAccessor())
                    .add(fooPropertyAccessor())
                    .add(new JsonIndexAccessor());
}

在父上下文中声明的自定义 PropertyAccessor 实例也会在任意子上下文中可用。 它们会被放置在结果列表的末尾(但在默认 org.springframework.context.expression.MapAccessoro.s.expression.spel.support.ReflectivePropertyAccessor 之前)。 如果您在子上下文中声明了一个具有相同 Bean ID 的 PropertyAccessor,它将覆盖父访问器。 在 <spel-property-accessors/> 内声明的 Bean 必须包含 'id' 属性。 最终的使用顺序如下:spring-doc.cadn.net.cn