Filter
消息过滤器用于根据某些条件(例如消息头值或消息内容本身)决定是否传递或丢弃 Message
。因此,消息过滤器与路由器类似,不同之处在于,对于从过滤器的输入通道接收的每条消息,这同一条消息可能被发送或不被发送到过滤器的输出通道。与路由器不同的是,它不会决定将消息发送到哪个消息通道,而只决定是否发送消息。
Message filters are used to decide whether a Message
should be passed along or dropped based on some criteria, such as a message header value or message content itself.
Therefore, a message filter is similar to a router, except that, for each message received from the filter’s input channel, that same message may or may not be sent to the filter’s output channel.
Unlike the router, it makes no decision regarding which message channel to send the message to but decides only whether to send the message at all.
如本节后面所述,过滤器还支持放弃通道。在某些情况下,它可以根据布尔条件扮演非常简单的路由器(或"`switch`")的角色。 |
As we describe later in this section, the filter also supports a discard channel. In certain cases, it can play the role of a very simple router (or “switch”), based on a boolean condition. |
在 Spring Integration 中,您可以将消息过滤器配置为委托给 MessageSelector
接口实现的消息端点。如下表所示,该接口本身非常简单:
In Spring Integration, you can configure a message filter as a message endpoint that delegates to an implementation of the MessageSelector
interface.
That interface is itself quite simple, as the following listing shows:
public interface MessageSelector {
boolean accept(Message<?> message);
}
MessageFilter
构造函数接受一个选择器实例,如下例所示:
The MessageFilter
constructor accepts a selector instance, as the following example shows:
MessageFilter filter = new MessageFilter(someSelector);
Configuring a Filter with Java, Groovy and Kotlin DSLs
Java DSL 提供的 IntegrationFlowBuilder
(也用作 Groovy 和 Kotlin DSL 的基础)为 filter()
运算符提供了许多重载方法。上述的 MessageSelector
抽象可以在 filter()
定义中用作 Lambda:
The IntegrationFlowBuilder
provided by the Java DSL (which is also used as a base for the Groovy and Kotlin DSLs) provides a number of overloaded methods for the filter()
operator.
The MessageSelector
abstraction mentioned above can be used as a Lambda in a filter()
definition:
-
Java DSL
-
Kotlin DSL
-
Groovy DSL
@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 的更多信息:
See more information about DSLs in the respective chapters:
Configuring a Filter with XML
结合命名空间和 SpEL,您可以使用极少的 Java 代码配置功能强大的过滤器。
In combination with the namespace and SpEL, you can configure powerful filters with very little Java code.
您可以使用 \<filter>
元素来创建一个消息选择端点。除了 input-channel
和 output-channel
属性外,它还需要一个 ref
属性。 ref
可以引用 MessageSelector
实现,如下面的示例所示:
You can use the <filter>
element is used to create a message-selecting endpoint.
In addition to input-channel
and output-channel
attributes, it requires a ref
attribute.
The ref
can point to a MessageSelector
implementation, as the following example shows:
<int:filter input-channel="input" ref="selector" output-channel="output"/>
<bean id="selector" class="example.MessageSelectorImpl"/>
也可以添加 method
属性。在这种情况下, ref
属性可以引用任何对象。引用的方法可以预期传入消息的 Message
类型或有效载荷类型。方法必须返回一个布尔值。如果方法返回“true”,消息将被发送到输出通道。下面的示例展示了如何配置一个使用 method
属性的过滤器:
Alternatively, you can add the method
attribute.
In that case, the ref
attribute may refer to any object.
The referenced method may expect either the Message
type or the payload type of inbound messages.
The method must return a boolean value.
If the method returns 'true', the message is sent to the output channel.
The following example shows how to configure a filter that uses the method
attribute:
<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
,如下面的示例所示:
If the selector or adapted POJO method returns false
, a few settings control the handling of the rejected message.
By default, (if configured as in the preceding example) rejected messages are silently dropped.
If rejection should instead result in an error condition, set the throw-exception-on-rejection
attribute to true
, as the following example shows:
<int:filter input-channel="input" ref="selector"
output-channel="output" throw-exception-on-rejection="true"/>
如果希望被拒绝的消息被路由到特定通道,请将该引用作为 discard-channel
提供,如下面的示例所示:
If you want rejected messages to be routed to a specific channel, provide that reference as the discard-channel
, as the following example shows:
<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
。框架的目标默认不是完全静默,需要设置一个显式选项(如果这是所需操作)。
If the throwExceptionOnRejection == false
and no discardChannel
is provided, the message is silently dropped and an o.s.i.filter.MessageFilter
instance just emits a warning log message (starting with version 6.1) about this discarded message.
To drop the message with no warning in the logs, a NullChannel
can be configured as the discardChannel
on the filter.
The goal of the framework is to not be completely silent, by default, requiring an explicit option to be set, if that is the desired behavior.
另请参阅 Advising Filters。
See also Advising Filters.
消息过滤器通常与发布-订阅通道结合使用。许多过滤器端点可能订阅同一通道,它们决定是否将消息传递给下一个端点,该端点可以是任何受支持类型(例如服务激活器)。这为使用具有单点对点输入通道和多个输出通道的消息路由器的更主动的方法提供了一种反应式替代方法。 |
Message filters are commonly used in conjunction with a publish-subscribe channel. Many filter endpoints may be subscribed to the same channel, and they decide whether to pass the message to the next endpoint, which could be any of the supported types (such as a service activator). This provides a reactive alternative to the more proactive approach of using a message router with a single point-to-point input channel and multiple output channels. |
如果自定义过滤器实现被引用在其他 <filter>
定义中,我们建议使用 ref
属性。但是,如果自定义过滤器实现仅作用于单个 <filter>
元素,您应当提供内部 bean 定义,如下面的示例所示:
We recommend using a ref
attribute if the custom filter implementation is referenced in other <filter>
definitions.
However, if the custom filter implementation is scoped to a single <filter>
element, you should provide an inner bean definition, as the following example shows:
<int:filter method="someMethod" input-channel="inChannel" output-channel="outChannel">
<beans:bean class="org.foo.MyCustomFilter"/>
</filter>
在同一`<filter>`配置中使用`ref`属性和内部处理程序定义是不允许的,因为它会创建一个不明确条件并抛出异常。 |
Using both the |
如果 ref
属性引用了扩展 MessageFilter
的 Bean(例如框架本身提供的过滤器),则可以通过直接向过滤器 Bean 注入输出信道来优化配置。在这种情况下,每个 ref
都必须是单独的 Bean 实例(或 prototype
-作用域的 Bean)或使用内部 <bean/>
配置类型。但是,仅当您不在过滤器 XML 定义中提供任何特定于过滤器的属性时,此优化才适用。如果您错误地从多个 Bean 引用相同的邮件处理程序,您将得到一个配置异常。
If the ref
attribute references a bean that extends MessageFilter
(such as filters provided by the framework itself), the configuration is optimized by injecting the output channel into the filter bean directly.
In this case, each ref
must be to a separate bean instance (or a prototype
-scoped bean) or use the inner <bean/>
configuration type.
However, this optimization applies only if you do not provide any filter-specific attributes in the filter XML definition.
If you inadvertently reference the same message handler from multiple beans, you get a configuration exception.
随着 SpEL 支持的引入,Spring Integration 向 filter 元素添加了 expression
属性。它可用于完全避免使用 Java 来实现简单过滤器,如下面的示例所示:
With the introduction of SpEL support, Spring Integration added the expression
attribute to the filter element.
It can be used to avoid Java entirely for simple filters, as the following example shows:
<int:filter input-channel="input" expression="payload.equals('nonsense')"/>
传递为表达式属性值字符串在评估上下文中作为 SpEL 表达式求值。如果您必须将表达式的结果包含在应用程序上下文的范围内,那么可以使用 `#{}`符号,如 SpEL reference documentation中定义的,如下例所示:
The string passed as the value of the expression attribute is evaluated as a SpEL expression with the message available in the evaluation context.
If you must include the result of an expression in the scope of the application context, you can use the #{}
notation, as defined in the SpEL reference documentation, as the following example shows:
<int:filter input-channel="input"
expression="payload.matches(#{filterPatterns.nonsensePattern})"/>
如果表达式本身需要是动态的,可以使用 'expression' 子元素。它为通过其键从 ExpressionSource
解析表达式提供了一个间接级别。这是一个策略接口,您可以直接实现,也可以依赖于 Spring Integration 中的一个版本,它从“资源包文件
”中加载表达式并可以在给定的秒数后检查它们是否有修改。所有这些都在下面的配置示例中进行了演示,在其中,如果基础文件被修改,表达式可以在一分钟内被重新加载:
If the expression itself needs to be dynamic, you can use an 'expression' sub-element.
That provides a level of indirection for resolving the expression by its key from an ExpressionSource
.
That is a strategy interface that you can implement directly, or you can rely upon a version available in Spring Integration that loads expressions from a “resource bundle” and can check for modifications after a given number of seconds.
All of this is demonstrated in the following configuration example, where the expression could be reloaded within one minute if the underlying file had been modified:
<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
属性。但是,在前面的示例中,我们展示了它以求完整。
If the ExpressionSource
bean is named expressionSource
, you need not provide the` source` attribute on the <expression>
element.
However, in the preceding example, we show it for completeness.
'config/integration/expressions.properties' 文件(或任何更具体的版本,具有将在加载资源包文件的典型方式中被解析的区域扩展名)可能包含一个键值对,如下面的示例所示:
The 'config/integration/expressions.properties' file (or any more-specific version with a locale extension to be resolved in the typical way that resource-bundles are loaded) can contain a key/value pair, as the following example shows:
filterPatterns.example=payload > 100
所有将 |
All of these examples that use |
Configuring a Filter with Annotations
下面的示例展示了如何通过使用注解来配置一个过滤器:
The following example shows how to configure a filter by using annotations:
public class PetFilter {
...
@Filter 1
public boolean dogsOnly(String input) {
...
}
}
1 | An annotation indicating that this method is to be used as a filter. It must be specified if this class is to be used as a filter. |
@Filter
注解也提供了 XML 元素提供的所有配置选项。
All the configuration options provided by the XML element are also available for the @Filter
annotation.
过滤器可以从 XML 中显式引用,也可以在类上定义 @MessageEndpoint
注解时通过类路径扫描自动检测。
The filter can be either referenced explicitly from XML or, if the @MessageEndpoint
annotation is defined on the class, detected automatically through classpath scanning.
See also Advising Endpoints Using Annotations.