邮件筛选器用于根据某些条件(如邮件标头值或邮件内容本身)来决定是否应传递或删除邮件。 因此,消息过滤器类似于路由器,不同之处在于,对于从过滤器的输入通道接收的每条消息,该消息可能会也可能不会发送到过滤器的输出通道。 与路由器不同,它不决定将消息发送到哪个消息通道,而只决定是否发送消息。MessageSpring中文文档

正如我们在本节后面所描述的,过滤器还支持丢弃通道。 在某些情况下,它可以根据布尔条件扮演非常简单的路由器(或“交换机”)的角色。

在 Spring Integration 中,您可以将消息过滤器配置为委托给接口实现的消息端点。 该界面本身非常简单,如以下列表所示:MessageSelectorSpring中文文档

public interface MessageSelector {

    boolean accept(Message<?> message);

}

构造函数接受选择器实例,如以下示例所示:MessageFilterSpring中文文档

MessageFilter filter = new MessageFilter(someSelector);
正如我们在本节后面所描述的,过滤器还支持丢弃通道。 在某些情况下,它可以根据布尔条件扮演非常简单的路由器(或“交换机”)的角色。

使用 Java、Groovy 和 Kotlin DSL 配置过滤器

Java DSL(也用作 Groovy 和 Kotlin DSL 的基础)提供的 Java DSL 为运算符提供了许多重载方法。 上面提到的抽象可以在定义中用作 Lambda:IntegrationFlowBuilderfilter()MessageSelectorfilter()Spring中文文档

@Bean
public IntegrationFlow someFlow() {
    return f -> f
              .<String>filter((payload) -> !"junk".equals(payload));
}
@Bean
fun someFlow() =
    integrationFlow {
        filter<String> { it != "junk" }
    }
@Bean
someFlow() {
    integrationFlow {
        filter String, { it != 'junk' }
    }
}

有关 DSL 的更多信息,请参阅相应的章节:Spring中文文档

使用 XML 配置筛选器

结合命名空间和 SpEL,您可以使用很少的 Java 代码配置强大的过滤器。Spring中文文档

您可以使用用于创建消息选择端点的元素。 除了 和 属性之外,它还需要一个属性。 can 指向实现,如以下示例所示:<filter>input-channeloutput-channelrefrefMessageSelectorSpring中文文档

<int:filter input-channel="input" ref="selector" output-channel="output"/>

<bean id="selector" class="example.MessageSelectorImpl"/>

或者,您可以添加该属性。 在这种情况下,该属性可以引用任何对象。 引用的方法可能需要入站消息的类型或有效负载类型。 该方法必须返回布尔值。 如果该方法返回“true”,则消息将发送到输出通道。 以下示例演示如何配置使用该属性的筛选器:methodrefMessagemethodSpring中文文档

<int:filter input-channel="input" output-channel="output"
    ref="exampleObject" method="someBooleanReturningMethod"/>

<bean id="exampleObject" class="example.SomeObject"/>

如果选择器或改编的 POJO 方法返回 ,则一些设置控制对被拒绝邮件的处理。 默认情况下,(如果按照前面的示例进行配置)被拒绝的邮件会以静默方式丢弃。 如果拒绝会导致错误条件,请将属性设置为 ,如以下示例所示:falsethrow-exception-on-rejectiontrueSpring中文文档

<int:filter input-channel="input" ref="selector"
    output-channel="output" throw-exception-on-rejection="true"/>

如果要将被拒绝的邮件路由到特定通道,请将该引用作为 提供,如以下示例所示:discard-channelSpring中文文档

<int:filter input-channel="input" ref="selector"
    output-channel="output" discard-channel="rejectedMessages"/>

如果提供了 and no,则该消息将以静默方式删除,并且实例只会发出有关此丢弃消息的警告日志消息(从版本 6.1 开始)。 若要删除日志中没有警告的消息,可以将 a 配置为过滤器上的 。 该框架的目标是在默认情况下不完全静默,如果这是所需的行为,则需要设置显式选项。throwExceptionOnRejection == falsediscardChannelo.s.i.filter.MessageFilterNullChanneldiscardChannelSpring中文文档

邮件筛选器通常与发布-订阅频道结合使用。 许多筛选器终结点可能订阅了同一通道,它们决定是否将消息传递到下一个终结点,该终结点可以是任何受支持的类型(例如服务激活器)。 这为使用具有单个点对点输入通道和多个输出通道的消息路由器的更主动的方法提供了一种反应式替代方案。

如果在其他定义中引用了自定义筛选器实现,我们建议使用属性。 但是,如果自定义筛选器实现的范围限定为单个元素,则应提供内 Bean 定义,如以下示例所示:ref<filter><filter>Spring中文文档

<int:filter method="someMethod" input-channel="inChannel" output-channel="outChannel">
  <beans:bean class="org.foo.MyCustomFilter"/>
</filter>
不允许在同一配置中同时使用属性和内部处理程序定义,因为它会创建不明确的条件并引发异常。ref<filter>
如果该属性引用了扩展的 Bean(例如框架本身提供的过滤器),则通过将输出通道直接注入过滤器 Bean 来优化配置。 在这种情况下,每个实例都必须指向单独的 Bean 实例(或 -scoped bean)或使用内部配置类型。 但是,仅当未在筛选器 XML 定义中提供任何特定于筛选器的属性时,此优化才适用。 如果无意中引用了多个 Bean 中的同一消息处理程序,则会出现配置异常。refMessageFilterrefprototype<bean/>

随着 SpEL 支持的引入,Spring Integration 将该属性添加到过滤器元素中。 对于简单的过滤器,它可以用来完全避免 Java,如以下示例所示:expressionSpring中文文档

<int:filter input-channel="input" expression="payload.equals('nonsense')"/>

作为表达式属性值传递的字符串将作为 SpEL 表达式进行计算,并在评估上下文中提供消息。 如果必须在应用程序上下文的范围内包含表达式的结果,则可以使用 SpEL 参考文档中定义的表示法,如以下示例所示:#{}Spring中文文档

<int:filter input-channel="input"
            expression="payload.matches(#{filterPatterns.nonsensePattern})"/>

如果表达式本身需要动态,则可以使用“表达式”子元素。 这为通过表达式的键从 . 这是一个策略接口,您可以直接实现,也可以依赖 Spring Integration 中可用的版本,该版本从“资源包”加载表达式,并可以在给定的秒数后检查修改。 以下配置示例演示了所有这些功能,如果修改了基础文件,则可以在一分钟内重新加载表达式:ExpressionSourceSpring中文文档

<int:filter input-channel="input" output-channel="output">
    <int:expression key="filterPatterns.example" source="myExpressions"/>
</int:filter>

<beans:bean id="myExpressions"
    class="o.s.i.expression.ReloadableResourceBundleExpressionSource">
    <beans:property name="basename" value="config/integration/expressions"/>
    <beans:property name="cacheSeconds" value="60"/>
</beans:bean>

如果 bean 被命名为 ,则无需在元素上提供 ' source' 属性。 但是,在前面的示例中,为了完整起见,我们展示了它。ExpressionSourceexpressionSource<expression>Spring中文文档

“config/integration/expressions.properties”文件(或任何具有区域设置扩展的更具体的版本,以加载资源包的典型方式进行解析)可以包含键/值对,如以下示例所示:Spring中文文档

filterPatterns.example=payload > 100
所有这些用作属性或子元素的示例也可以应用于 transformer、router、splitter、service-activator 和 header-enricher 元素中。 给定组件类型的语义和角色将影响对评估结果的解释,就像解释方法调用的返回值一样。 例如,表达式可以返回路由器组件将作为消息通道名称处理的字符串。 但是,根据 Message 作为根对象评估表达式并解析 Bean 名称(如果前缀为“@”)的基本功能在 Spring Integration 中的所有核心 EIP 组件中是一致的。expression
邮件筛选器通常与发布-订阅频道结合使用。 许多筛选器终结点可能订阅了同一通道,它们决定是否将消息传递到下一个终结点,该终结点可以是任何受支持的类型(例如服务激活器)。 这为使用具有单个点对点输入通道和多个输出通道的消息路由器的更主动的方法提供了一种反应式替代方案。
不允许在同一配置中同时使用属性和内部处理程序定义,因为它会创建不明确的条件并引发异常。ref<filter>
如果该属性引用了扩展的 Bean(例如框架本身提供的过滤器),则通过将输出通道直接注入过滤器 Bean 来优化配置。 在这种情况下,每个实例都必须指向单独的 Bean 实例(或 -scoped bean)或使用内部配置类型。 但是,仅当未在筛选器 XML 定义中提供任何特定于筛选器的属性时,此优化才适用。 如果无意中引用了多个 Bean 中的同一消息处理程序,则会出现配置异常。refMessageFilterrefprototype<bean/>
所有这些用作属性或子元素的示例也可以应用于 transformer、router、splitter、service-activator 和 header-enricher 元素中。 给定组件类型的语义和角色将影响对评估结果的解释,就像解释方法调用的返回值一样。 例如,表达式可以返回路由器组件将作为消息通道名称处理的字符串。 但是,根据 Message 作为根对象评估表达式并解析 Bean 名称(如果前缀为“@”)的基本功能在 Spring Integration 中的所有核心 EIP 组件中是一致的。expression

使用注释配置过滤器

以下示例演示如何使用批注配置筛选器:Spring中文文档

public class PetFilter {
    ...
    @Filter  (1)
    public boolean dogsOnly(String input) {
        ...
    }
}
1 指示此方法将用作筛选器的批注。 如果要将此类用作筛选器,则必须指定它。

XML 元素提供的所有配置选项也可用于批注。@FilterSpring中文文档

筛选器可以从 XML 显式引用,或者(如果在类上定义了注释),则通过类路径扫描自动检测。@MessageEndpointSpring中文文档

1 指示此方法将用作筛选器的批注。 如果要将此类用作筛选器,则必须指定它。