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

过滤器

消息过滤器用于根据某些标准(如消息头值或消息本身)决定是否应该将一个Message传递下去或者丢弃。 因此,一个消息过滤器类似于路由器,但不同的是,对于过滤器输入通道接收到的每个消息,该消息可能会或不会被发送到过滤器的输出通道。 与路由器不同的是,它不涉及决定将消息发送到哪个消息通道的问题,只决定是否发送此消息。spring-doc.cadn.net.cn

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

在Spring Integration中,您可以将消息过滤器配置为委托给MessageSelector接口实现的消息端点。 该接口本身相当简单,如下所示:spring-doc.cadn.net.cn

public interface MessageSelector {

    boolean accept(Message<?> message);

}

The MessageFilter 构造函数接受一个选择器实例,如下例所示:spring-doc.cadn.net.cn

MessageFilter filter = new MessageFilter(someSelector);

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

由 Java DSL(也用作 Groovy 和 Kotlin DSL 的基础)提供的IntegrationFlowBuilderfilter()运算符提供了多个重载方法。 上述提到的MessageSelector抽象可以在filter()定义中作为 Lambda 使用:spring-doc.cadn.net.cn

@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' }
    }
}

在相应的章节中查看关于DSLs的更多信息:spring-doc.cadn.net.cn

使用 XML 配置过滤器

结合命名空间和SpEL,您可以使用非常少的Java代码配置强大的过滤器。spring-doc.cadn.net.cn

您可以使用<filter>元素来创建一个消息选择端点。除了input-channeloutput-channel属性外,它还需要一个ref属性。
ref可以指向一个MessageSelector实现,如下例所示:spring-doc.cadn.net.cn

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

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

Alternatively, you可以添加method属性。
在这种情况下,ref属性可以引用任何对象。引用的方法可能期望Message类型或入站消息的负载类型。方法必须返回一个布尔值。
如果该方法返回'true',则消息将发送到输出通道。
以下示例展示了如何配置使用method属性的过滤器:spring-doc.cadn.net.cn

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

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

如果选择器或适配的 POJO 方法返回 false,则有几个设置控制被拒绝消息的处理方式。 默认情况下(如果按前一个示例配置),被拒绝的消息会被静默丢弃。 如果希望拒绝导致错误条件,请将 throw-exception-on-rejection 属性设置为 true,如下例所示:spring-doc.cadn.net.cn

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

如果要将拒绝的消息路由到特定的通道,请提供该引用作为discard-channel,如下例所示:spring-doc.cadn.net.cn

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

如果未提供throwExceptionOnRejection == false和无discardChannel,消息将被静默丢弃,并在日志中仅发出警告信息(从版本6.1开始)。 要不带任何警告的日志信息就丢弃消息,可以在过滤器上配置一个NullChannel作为discardChannel。 框架的目标是默认情况下不要完全静默,如果这是所需行为,则需要显式设置选项。spring-doc.cadn.net.cn

消息过滤器通常与发布/订阅频道一起使用。 许多过滤端点可以订阅同一个频道,并决定是否将消息传递给下一个端点,这个下一个端点可能是任何支持的类型(例如服务激活器)。 这提供了一种相对于使用单个点对点输入频道和多个输出频道的消息路由器而言更加响应式的替代方案。

我们推荐在自定义过滤器实现被其他<filter>定义引用时,使用ref属性。 然而,如果自定义过滤器实现仅限于单个<filter>元素,则您应该提供一个内部bean定义,如下例所示:spring-doc.cadn.net.cn

<int:filter method="someMethod" input-channel="inChannel" output-channel="outChannel">
  <beans:bean class="org.foo.MyCustomFilter"/>
</filter>
在同一个<filter>配置中同时使用ref属性和内嵌处理器定义是不允许的,因为这会导致一种模棱两可的情况并抛出异常。
如果 ref 属性引用了一个扩展了 MessageFilter 的 bean(例如框架本身提供的过滤器),则配置将通过直接注入输出通道来优化到过滤器 bean。 在这种情况下,每个 ref 必须是单独的 bean 实例(或 prototype-作用域的 bean)或者使用内部的 <bean/> 配置类型。 然而,这种优化仅在您未在过滤器 XML 定义中提供任何特定于过滤器的属性时才适用。 如果您意外地从多个 bean 引用了同一个消息处理器,则会得到一个配置异常。

随着SpEL支持的引入,Spring Integration 添加了 expression 属性到 filter 元素。 它可以用于避免完全使用 Java 来实现简单的过滤器,如下例所示:spring-doc.cadn.net.cn

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

将作为表达式属性值传递的字符串作为 SpEL 表达式进行评估,其中的消息在评估上下文中可用。 如果必须将在应用程序上下文范围内包含表达式的结果,则可以使用 #{} 符号,如SpEL 参考文档中定义的那样,如下例所示:spring-doc.cadn.net.cn

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

如果表达式本身需要是动态的,您可以使用'expression'子元素。 这提供了通过键从ExpressionSource解析表达式的间接层。 这是一个策略接口,您可以直接实现它,或者依赖Spring Integration中提供的版本,该版本可以从“资源包”加载表达式,并能在给定秒数后检查是否发生了修改。 以下配置示例演示了所有这些功能:如果底层文件被修改,表达式可以在一分钟内重新加载:spring-doc.cadn.net.cn

<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>

如果 ExpressionSource bean 的名称为 expressionSource,则无需在 <expression> 元素上提供 `source` 属性。 不过,在前面的示例中,为了完整性我们仍展示了它。spring-doc.cadn.net.cn

'config/integration/expressions.properties' 文件(或任何带有区域设置扩展的更具体的版本,将以加载资源包的典型方式解析)可以包含键/值对,如下例所示:spring-doc.cadn.net.cn

filterPatterns.example=payload > 100
所有将 expression 作为属性或子元素使用的示例,同样可以应用于 transformer、router、splitter、service-activator 和 header-enricher 元素。 给定组件类型的语义和作用会影响对求值结果的解释,这与方法调用的返回值被解释的方式相同。 例如,表达式可以返回字符串,这些字符串将被 router 组件视为消息通道名称。 然而,在 Spring Integration 的所有核心 EIP 组件中,以消息为根对象评估表达式并在前缀为 '@' 时解析 Bean 名称的底层功能是一致的。

使用注解配置过滤器

以下示例展示了如何使用注解配置一个过滤器:spring-doc.cadn.net.cn

public class PetFilter {
    ...
    @Filter  (1)
    public boolean dogsOnly(String input) {
        ...
    }
}
1 这是一个指示此方法作为过滤器使用的注解。 如果要将此类用作过滤器,则必须指定此注解。

XML 元素提供的所有配置选项也同样适用于 @Configuration 注解。spring-doc.cadn.net.cn

该过滤器可以从XML中显式引用,或者如果类上定义了@MessageEndpoint注解,则可以通过类路径扫描自动检测。spring-doc.cadn.net.cn