フィルター

メッセージフィルターは、メッセージヘッダー値やメッセージコンテンツ自体などの条件に基づいて、Message を渡すかドロップするかを決定するために使用されます。メッセージフィルターはルーターに似ていますが、フィルターの入力チャネルから受信した各メッセージについて、同じメッセージがフィルターの出力チャネルに送信される場合と送信されない場合があります。ルーターとは異なり、メッセージを送信するメッセージチャネルに関する決定は行いませんが、メッセージを送信するかどうかのみを決定します。

このセクションの後半で説明するように、フィルターは破棄チャネルもサポートします。場合によっては、ブール条件に基づいて、非常に単純なルーター(または「スイッチ」)のロールを果たすことができます。

Spring Integration では、MessageSelector インターフェースの実装に委譲するメッセージエンドポイントとしてメッセージフィルターを構成できます。次のように、このインターフェース自体は非常にシンプルです。

public interface MessageSelector {

    boolean accept(Message<?> message);

}

MessageFilter コンストラクターは、次の例に示すように、セレクターインスタンスを受け入れます。

MessageFilter filter = new MessageFilter(someSelector);

名前空間と SpEL を組み合わせて、ごくわずかな Java コードで強力なフィルターを構成できます。

XML を使用したフィルターの構成

<filter> 要素を使用して、メッセージ選択エンドポイントを作成できます。input-channel および output-channel 属性に加えて、ref 属性が必要です。次の例に示すように、ref は MessageSelector 実装を指すことができます。

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

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

または、method 属性を追加できます。その場合、ref 属性は任意のオブジェクトを参照できます。参照されるメソッドは、受信メッセージの Message 型またはペイロード型のいずれかを予期する場合があります。メソッドはブール値を返す必要があります。メソッドが "true" を返す場合、メッセージは出力チャネルに送信されます。次の例は、method 属性を使用するフィルターを構成する方法を示しています。

<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 に設定します。

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

拒否されたメッセージを特定のチャネルにルーティングする場合は、次の例に示すように、その参照を discard-channel として提供します。

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

アドバイスフィルターも参照してください。

メッセージフィルターは、一般にパブリッシュ / サブスクライブチャネルと組み合わせて使用されます。多くのフィルターエンドポイントは同じチャネルにサブスクライブでき、サポートされている型(サービスアクティベーターなど)のいずれかである可能性がある次のエンドポイントにメッセージを渡すかどうかを決定します。これは、単一のポイントツーポイント入力チャネルと複数の出力チャネルを備えたメッセージルーターを使用する、より積極的なアプローチのリアクティブな代替手段を提供します。

カスタムフィルターの実装が他の <filter> 定義で参照されている場合は、ref 属性を使用することをお勧めします。ただし、カスタムフィルターの実装が単一の <filter> 要素にスコープされている場合は、次の例に示すように、内部 Bean 定義を提供する必要があります。

<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 -scoped Bean)に属しているか、内部 <bean/> 構成型を使用する必要があります。ただし、この最適化は、フィルター XML 定義にフィルター固有の属性を指定しない場合にのみ適用されます。誤って複数の Bean から同じメッセージハンドラーを参照すると、構成例外が発生します。

SpEL サポートの導入により、Spring Integration は expression 属性をフィルター要素に追加しました。次の例に示すように、単純なフィルターで Java を完全に回避するために使用できます。

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

expression 属性の値として渡された文字列は、評価コンテキストで利用可能なメッセージとともに SpEL 式として評価されます。アプリケーションコンテキストのスコープに式の結果を含める必要がある場合は、次の例に示すように、SpEL リファレンスドキュメントで定義されている #{} 表記を使用できます。

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

式自体を動的にする必要がある場合は、「式」サブ要素を使用できます。それは、ExpressionSource からのキーによって式を解決するための間接性のレベルを提供します。これは、直接実装できる戦略インターフェースです。または、「リソースバンドル」から式をロードし、指定された秒数後に変更を確認できる Spring Integration で利用可能なバージョンに依存できます。このすべては、基になるファイルが変更された場合に 1 分以内に式をリロードできる次の構成例で示されています。

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

<beans:bean id="myExpressions" 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` 属性を指定する必要はありません。ただし、前の例では、完全を期すために示しています。

次の例に示すように、"config/integration/expressions.properties" ファイル(またはリソースバンドルがロードされる一般的な方法で解決されるロケール拡張機能を備えたより具体的なバージョン)には、キー / 値のペアを含めることができます。

filterPatterns.example=payload > 100
属性またはサブ要素として expression を使用するこれらの例はすべて、トランスフォーマー、ルーター、スプリッター、サービスアクティベーター、ヘッダーエンリッチャー要素内でも適用できます。メソッド呼び出しの戻り値が解釈されるのと同じように、与えられたコンポーネント型のセマンティクスとロールは評価結果の解釈に影響を与えます。例: 式は、ルーターコンポーネントによってメッセージチャネル名として扱われる文字列を返すことができます。ただし、メッセージに対してルートオブジェクトとして式を評価し、接頭辞 "@" が付いている場合に Bean 名を解決する基本機能は、Spring Integration 内のすべてのコア EIP コンポーネントで一貫しています。

アノテーション付きのフィルターの構成

次の例は、アノテーションを使用してフィルターを構成する方法を示しています。

public class PetFilter {
    ...
    @Filter  (1)
    public boolean dogsOnly(String input) {
        ...
    }
}
1 このメソッドがフィルターとして使用されることを示すアノテーション。このクラスをフィルターとして使用する場合は、指定する必要があります。

XML 要素によって提供されるすべての構成オプションは、@Filter アノテーションでも使用できます。

フィルターは、XML から明示的に参照するか、クラスで @MessageEndpoint アノテーションが定義されている場合、クラスパススキャンにより自動的に検出されます。