【Java】Spring:を使用したメッセージのルーティングで処理を場合分けする

■処理概要

payloadの値について、「A」、「B」、「その他(other)」で<int:router>を使用して場合分けを行い、それぞれ出力する内容を変更する。

・payloadの設定値

物理名論理名用途
typeメッセージタイプ「A」、「B」、「その他(other)」で場合分け
messageメッセージ出力するメッセージ
router
router
payload
– type
– message
payload…
typeAChannel
typeAChannel
typeBChannel
typeBChannel
DefaultChannel
DefaultChannel
A
A
B
B
Other
Other
Text is not SVG – cannot display

■<int:router>の概要

メッセージの内容に応じて「どのチャネルに送るか」を決定する要素。
つまり「条件分岐の司令塔」みたいなもの。

▼主な用途

  • メッセージの属性(payloadやヘッダー)に応じて分岐
  • 複数の処理フローにルーティング
  • 条件に合致しない場合の「デフォルトチャネル」も設定可

▼使う属性

属性説明
input-channel処理の入口
expressionSpring Expression Languageで条件記述(※1)
ref / methodJavaのBeanを使ってルーティング
default-output-channel条件に合致しない場合の送信先
<int:mapping>値からチャンネルへのマッピング

(※1)条件記述例

  • payloadの値で分岐:expression=”payload.status”
  • ヘッダーで分岐:expression=”headers[‘routeTo’]”

■ディレクトリ構造

実装するモジュールのディレクトリ階層を以下に示す。

■pom.xml

実装するモジュールのpom.xmlの設定を以下に示す。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.4.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>router-sample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>router-sample</name>
	<description>spring integration: router sample</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-integration</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

■サンプルコード

・RouterSampleConfig.java

package com.example.router_sample.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:router-sample-context.xml")
public class RouterSampleConfig {

}

・MessageHandler.java

package com.example.router_sample.handler;

import com.example.router_sample.message.MessagePayload;

public class MessageHandler {

  public void handleA(MessagePayload payload) {
    System.out.println("Aタイプの処理: " + payload.getMessage());
  }

  public void handleB(MessagePayload payload) {
    System.out.println("Bタイプの処理: " + payload.getMessage());
  }

  public void handleDefault(MessagePayload payload) {
    System.out.println("未定義タイプ: " + payload.getMessage());
  }
}


・MessagePayload.java

package com.example.router_sample.message;

public class MessagePayload {

  private final String type;
  private final String message;

  public MessagePayload(String type, String message) {
    this.type = type;
    this.message = message;
  }

  public String getType() {
    return type;
  }

  public String getMessage() {
    return message;
  }
}

・RouterSampleApplication.java

package com.example.router_sample;

import com.example.router_sample.message.MessagePayload;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;

@SpringBootApplication
public class RouterSampleApplication {

  public static void main(String[] args) {
    SpringApplication.run(RouterSampleApplication.class, args);
  }

  @Bean
  public CommandLineRunner run(@Qualifier("inputChannel") MessageChannel inputChannel) {
    return args -> {
      // ここでtypeとメッセージを設定
      MessagePayload payload = new MessagePayload("A", "ルーティングテストA");
      Message<?> message = MessageBuilder.withPayload(payload).build();
      inputChannel.send(message);
    };
  }
}

・router-sample-context.xml

<beans xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.springframework.org/schema/beans"
  xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/integration
         http://www.springframework.org/schema/integration/spring-integration.xsd">

  <!-- 入出力チャネル -->
  <int:channel id="inputChannel"/>
  <int:channel id="typeAChannel"/>
  <int:channel id="typeBChannel"/>
  <int:channel id="defaultChannel"/>

  <!-- ルーター定義 -->
  <int:router default-output-channel="defaultChannel" expression="payload.type"
    input-channel="inputChannel">
    <int:mapping channel="typeAChannel" value="A"/>
    <int:mapping channel="typeBChannel" value="B"/>
  </int:router>

  <!-- 処理 -->
  <int:service-activator input-channel="defaultChannel" method="handleDefault" ref="handler"/>
  <int:service-activator input-channel="typeAChannel" method="handleA" ref="handler"/>
  <int:service-activator input-channel="typeBChannel" method="handleB" ref="handler"/>

  <!-- bean -->
  <bean class="com.example.router_sample.handler.MessageHandler" id="handler"/>
</beans>

■実行結果

・タイプ:A、メッセージ:ルーティングテストAの場合

Aタイプの処理: ルーティングテストA

・タイプ:B、メッセージ:ルーティングテストBの場合

Bタイプの処理: ルーティングテストB

・タイプ:C、メッセージ:ルーティングテストCの場合

未定義タイプ: ルーティングテストC

コメント

タイトルとURLをコピーしました