Filter

邮件过滤器用于决定Message应根据某些条件(如消息头值或消息内容本身)传递或删除。 因此,消息过滤器类似于路由器,不同之处在于,对于从过滤器的 input 通道接收的每条消息,同一条消息可能会也可能不会发送到过滤器的输出通道。 与路由器不同,它不决定将消息发送到哪个消息通道,而只决定是否发送消息。spring-doc.cadn.net.cn

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

在 Spring 集成中,您可以将消息过滤器配置为消息端点,该端点委托给MessageSelector接口。 该接口本身非常简单,如下面的清单所示:spring-doc.cadn.net.cn

public interface MessageSelector {

    boolean accept(Message<?> message);

}

MessageFilterconstructor 接受一个 selector 实例,如下例所示:spring-doc.cadn.net.cn

MessageFilter filter = new MessageFilter(someSelector);

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

IntegrationFlowBuilder由 Java DSL(也用作 Groovy 和 Kotlin DSL 的基础)提供了许多重载方法filter()算子。 这MessageSelectorabstraction 可以用作filter()定义: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' }
    }
}

有关DSL的更多信息,请参阅相应的章节: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"/>

或者,您也可以添加method属性。 在这种情况下,refattribute 可以引用任何对象。 引用的方法可能需要Messagetype 或入站消息的有效负载类型。 该方法必须返回布尔值。 如果该方法返回 '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中,有一些设置控制对被拒绝消息的处理。 默认情况下,(如果配置如上例所示)被拒绝的消息将被静默丢弃。 如果 rejection 应改为导致错误条件,请将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时,该消息将被静默丢弃,并且o.s.i.filter.MessageFilter实例 仅发出有关此丢弃消息的警告日志消息(从版本 6.1 开始)。 要删除日志中没有警告的消息,请使用NullChannel可以配置为discardChannel在过滤器上。 框架的目标是默认情况下不是完全静默的,如果这是所需的行为,则需要设置显式选项。spring-doc.cadn.net.cn

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

我们建议使用ref属性(如果自定义过滤器实现在其他<filter>定义。 但是,如果自定义过滤器实现的范围限定为单个<filter>元素,你应该提供一个内部 Bean 定义,如下例所示:spring-doc.cadn.net.cn

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

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

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

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

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

如果表达式本身需要是动态的,则可以使用 'expression' 子元素。 这为通过 key 从ExpressionSource. 这是一个可以直接实现的策略接口,或者你可以依赖 Spring 集成中提供的版本,该版本从“资源包”加载表达式,并可以在给定的秒数后检查修改。 以下配置示例演示了所有这些,其中,如果底层文件已被修改,则可以在一分钟内重新加载表达式: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>

如果ExpressionSourcebean 被命名为expressionSource,则无需在<expression>元素。 但是,在前面的示例中,我们展示了它以保证完整性。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 组件将视为消息通道名称的字符串。 但是,根据作为根对象的消息评估表达式并解析前缀为“@”的 bean 名称的底层功能在 Spring 集成中的所有核心 EIP 组件中是一致的。

配置带有注释的过滤器

以下示例显示如何使用注释配置筛选条件:spring-doc.cadn.net.cn

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

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

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