SpringIntegration消息路由之Router的條件路由與過濾功能
引言
在企業(yè)集成架構(gòu)中,消息路由是一個(gè)至關(guān)重要的環(huán)節(jié),它負(fù)責(zé)根據(jù)預(yù)定的規(guī)則將消息分發(fā)到不同的目標(biāo)通道。Spring Integration作為企業(yè)集成模式的實(shí)現(xiàn)框架,提供了強(qiáng)大的Router組件來滿足各種復(fù)雜的路由需求。Router可以根據(jù)消息的內(nèi)容、消息頭或其它條件,智能地決定消息的流向,從而使系統(tǒng)的各個(gè)組件能夠?qū)W⒂谧约旱暮诵墓δ?,提高了系統(tǒng)的模塊化程度和可維護(hù)性。本文將深入探討Spring Integration中Router的實(shí)現(xiàn)方式和應(yīng)用場景,特別是條件路由和消息過濾的相關(guān)技術(shù),通過具體示例展示如何在實(shí)際項(xiàng)目中有效地使用這些功能。
一、Router基礎(chǔ)概念
Router是Spring Integration中的核心組件之一,其主要職責(zé)是根據(jù)特定的條件將輸入消息路由到一個(gè)或多個(gè)輸出通道。通過Router,可以構(gòu)建靈活的消息流,實(shí)現(xiàn)業(yè)務(wù)邏輯的動(dòng)態(tài)分支處理。Spring Integration提供了多種類型的Router實(shí)現(xiàn),包括PayloadTypeRouter、HeaderValueRouter、RecipientListRouter、ExpressionEvaluatingRouter等,開發(fā)人員可以根據(jù)具體需求選擇合適的Router類型。Router的工作原理是接收來自輸入通道的消息,根據(jù)配置的路由規(guī)則評估消息,然后決定將消息發(fā)送到哪個(gè)或哪些輸出通道。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@Configuration
public class BasicRouterConfig {
// 定義通道
@Bean
public MessageChannel inputChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel orderChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel inventoryChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel customerChannel() {
return new DirectChannel();
}
// 基礎(chǔ)路由器實(shí)現(xiàn)
@Bean
@Router(inputChannel = "inputChannel")
public String route(Message<?> message) {
// 根據(jù)消息的不同類型路由到不同的通道
Object payload = message.getPayload();
if (payload instanceof Order) {
return "orderChannel";
} else if (payload instanceof InventoryItem) {
return "inventoryChannel";
} else if (payload instanceof Customer) {
return "customerChannel";
} else {
throw new IllegalArgumentException("未知消息類型: " + payload.getClass().getName());
}
}
// 示例數(shù)據(jù)類
public static class Order {
private String orderId;
// 其他字段省略
}
public static class InventoryItem {
private String itemId;
// 其他字段省略
}
public static class Customer {
private String customerId;
// 其他字段省略
}
}二、條件路由實(shí)現(xiàn)
條件路由是指根據(jù)消息內(nèi)容或消息頭信息中的特定條件,將消息路由到不同的目標(biāo)通道。Spring Integration提供了多種方式來實(shí)現(xiàn)條件路由,包括使用SpEL表達(dá)式、Java DSL和基于注解的配置。ExpressionEvaluatingRouter允許使用SpEL表達(dá)式定義路由條件,使得復(fù)雜的路由邏輯可以通過簡潔的表達(dá)式實(shí)現(xiàn)。通過條件路由,系統(tǒng)可以根據(jù)業(yè)務(wù)規(guī)則動(dòng)態(tài)地決定消息的處理流程,例如根據(jù)訂單金額將訂單分為高優(yōu)先級和普通優(yōu)先級處理,或者根據(jù)客戶類型提供不同級別的服務(wù)。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.router.ExpressionEvaluatingRouter;
import org.springframework.messaging.MessageChannel;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ConditionalRouterConfig {
// 使用SpEL表達(dá)式的條件路由器
@Bean
@Router(inputChannel = "orderInputChannel")
public ExpressionEvaluatingRouter orderRouter() {
ExpressionEvaluatingRouter router = new ExpressionEvaluatingRouter("payload.amount > 1000 ? 'vipOrderChannel' : 'regularOrderChannel'");
router.setChannelMapping("true", "vipOrderChannel");
router.setChannelMapping("false", "regularOrderChannel");
return router;
}
// 使用Java DSL的方式配置條件路由
@Bean
public org.springframework.integration.dsl.IntegrationFlow conditionRoutingFlow() {
return org.springframework.integration.dsl.IntegrationFlows
.from("paymentInputChannel")
.<Payment, String>route(
payment -> {
if (payment.getAmount() < 100) {
return "smallPaymentChannel";
} else if (payment.getAmount() < 1000) {
return "mediumPaymentChannel";
} else {
return "largePaymentChannel";
}
},
mapping -> mapping
.subFlowMapping("smallPaymentChannel", sf -> sf
.handle(message -> {
System.out.println("處理小額支付: " + message.getPayload());
}))
.subFlowMapping("mediumPaymentChannel", sf -> sf
.handle(message -> {
System.out.println("處理中額支付: " + message.getPayload());
}))
.subFlowMapping("largePaymentChannel", sf -> sf
.handle(message -> {
System.out.println("處理大額支付: " + message.getPayload());
}))
)
.get();
}
// 多條件路由示例
@Bean
@Router(inputChannel = "customerInputChannel")
public String routeCustomer(Customer customer) {
// 根據(jù)客戶類型和信用評分路由
if (customer.getType().equals("VIP") && customer.getCreditScore() > 700) {
return "premiumServiceChannel";
} else if (customer.getType().equals("VIP")) {
return "vipServiceChannel";
} else if (customer.getCreditScore() > 700) {
return "priorityServiceChannel";
} else {
return "regularServiceChannel";
}
}
// 示例數(shù)據(jù)類
public static class Payment {
private double amount;
public double getAmount() {
return amount;
}
}
public static class Customer {
private String type;
private int creditScore;
public String getType() {
return type;
}
public int getCreditScore() {
return creditScore;
}
}
}三、基于消息頭的路由
在企業(yè)集成場景中,消息頭通常包含了重要的元數(shù)據(jù),如消息類型、優(yōu)先級、來源系統(tǒng)等信息,這些信息對于路由決策十分有用。HeaderValueRouter專門用于根據(jù)消息頭的值進(jìn)行路由,簡化了基于消息頭的路由配置。通過消息頭路由,可以在不解析消息內(nèi)容的情況下快速做出路由決策,提高了系統(tǒng)性能,同時(shí)也使得路由邏輯與業(yè)務(wù)邏輯分離,增強(qiáng)了系統(tǒng)的模塊化程度。這種路由方式特別適合于處理來自不同系統(tǒng)的消息,或者需要根據(jù)消息的元數(shù)據(jù)進(jìn)行分類處理的場景。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.router.HeaderValueRouter;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
@Configuration
public class HeaderBasedRouterConfig {
// 基于消息頭的路由器
@Bean
@Router(inputChannel = "requestChannel")
public HeaderValueRouter messageTypeRouter() {
HeaderValueRouter router = new HeaderValueRouter("message-type");
router.setChannelMapping("ORDER", "orderProcessingChannel");
router.setChannelMapping("INVENTORY", "inventoryManagementChannel");
router.setChannelMapping("SHIPPING", "shippingChannel");
router.setChannelMapping("PAYMENT", "paymentProcessingChannel");
// 設(shè)置默認(rèn)通道,當(dāng)沒有匹配的消息頭值時(shí)使用
router.setDefaultOutputChannelName("unknownMessageChannel");
return router;
}
// 消息頭注入示例
@Bean
public org.springframework.integration.transformer.HeaderEnricher headerEnricher() {
Map<String, Object> headersToAdd = new HashMap<>();
headersToAdd.put("message-type", "ORDER");
headersToAdd.put("priority", "HIGH");
return new org.springframework.integration.transformer.HeaderEnricher(headersToAdd);
}
// 發(fā)送消息的示例方法
public void sendMessage() {
// 創(chuàng)建包含消息頭的消息
Message<String> orderMessage = MessageBuilder
.withPayload("訂單數(shù)據(jù)內(nèi)容")
.setHeader("message-type", "ORDER")
.setHeader("priority", "HIGH")
.build();
Message<String> inventoryMessage = MessageBuilder
.withPayload("庫存數(shù)據(jù)內(nèi)容")
.setHeader("message-type", "INVENTORY")
.setHeader("priority", "MEDIUM")
.build();
// 將消息發(fā)送到requestChannel,路由器會(huì)根據(jù)message-type頭進(jìn)行路由
requestChannel().send(orderMessage);
requestChannel().send(inventoryMessage);
}
@Bean
public org.springframework.messaging.MessageChannel requestChannel() {
return new org.springframework.integration.channel.DirectChannel();
}
}四、動(dòng)態(tài)路由與路由表
在某些復(fù)雜的集成場景中,路由規(guī)則可能需要根據(jù)運(yùn)行時(shí)的條件動(dòng)態(tài)變化,或者需要在配置文件中定義而不是硬編碼在代碼中。Spring Integration提供了動(dòng)態(tài)路由的能力,允許開發(fā)人員在運(yùn)行時(shí)修改路由規(guī)則或從外部配置中加載路由表。AbstractMappingMessageRouter是實(shí)現(xiàn)動(dòng)態(tài)路由的基礎(chǔ)類,它維護(hù)了一個(gè)通道映射表,可以在運(yùn)行時(shí)更新。這種方式使得系統(tǒng)能夠適應(yīng)業(yè)務(wù)規(guī)則的變化,而無需修改代碼和重新部署,提高了系統(tǒng)的靈活性和可維護(hù)性。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.handler.annotation.Header;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@Configuration
public class DynamicRouterConfig {
@Autowired
private RoutingRuleService routingRuleService;
// 自定義動(dòng)態(tài)路由器
@Bean
@ServiceActivator(inputChannel = "dynamicRoutingChannel")
public AbstractMappingMessageRouter dynamicRouter() {
return new AbstractMappingMessageRouter() {
@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
// 從服務(wù)中獲取最新的路由規(guī)則
Map<String, String> routingRules = routingRuleService.getRoutingRules();
// 根據(jù)消息內(nèi)容或頭信息確定路由鍵
String routingKey = extractRoutingKey(message);
// 根據(jù)路由鍵查找目標(biāo)通道名稱
String channelName = routingRules.getOrDefault(routingKey, "defaultChannel");
// 獲取目標(biāo)通道并返回
MessageChannel channel = getChannelResolver().resolveDestination(channelName);
return Collections.singleton(channel);
}
private String extractRoutingKey(Message<?> message) {
// 實(shí)現(xiàn)從消息中提取路由鍵的邏輯
// 這里簡化為從特定的消息頭中獲取
return (String) message.getHeaders().get("routing-key");
}
};
}
// 路由規(guī)則服務(wù),用于管理和提供路由規(guī)則
@Bean
public RoutingRuleService routingRuleService() {
return new RoutingRuleService();
}
// 路由規(guī)則管理服務(wù)
public static class RoutingRuleService {
private Map<String, String> routingRules = new HashMap<>();
public RoutingRuleService() {
// 初始化默認(rèn)路由規(guī)則
routingRules.put("ORDER", "orderChannel");
routingRules.put("INVENTORY", "inventoryChannel");
routingRules.put("CUSTOMER", "customerChannel");
}
public Map<String, String> getRoutingRules() {
return routingRules;
}
public void updateRoutingRule(String key, String channelName) {
routingRules.put(key, channelName);
}
public void loadRoutingRules(Properties properties) {
properties.forEach((k, v) -> routingRules.put(k.toString(), v.toString()));
}
}
// 路由規(guī)則更新API
@Bean
@ServiceActivator(inputChannel = "routingRuleUpdateChannel")
public void updateRoutingRule(Message<RoutingRuleUpdate> message) {
RoutingRuleUpdate update = message.getPayload();
routingRuleService.updateRoutingRule(update.getKey(), update.getChannelName());
}
// 路由規(guī)則更新請求
public static class RoutingRuleUpdate {
private String key;
private String channelName;
// 省略getter和setter
}
}五、消息過濾與選擇性路由
消息過濾是路由的一種特殊形式,它基于特定條件決定是否允許消息繼續(xù)流轉(zhuǎn)。Spring Integration的Filter組件用于實(shí)現(xiàn)這一功能,它可以根據(jù)消息的內(nèi)容或消息頭信息過濾掉不符合條件的消息。過濾器可以作為獨(dú)立的組件使用,也可以與路由器結(jié)合使用,實(shí)現(xiàn)更復(fù)雜的路由邏輯。例如,在處理訂單消息時(shí),可以過濾掉無效的訂單,或者將不同類型的訂單路由到不同的處理通道。這種選擇性路由機(jī)制使得系統(tǒng)能夠更有針對性地處理不同類型的消息,提高了處理效率和系統(tǒng)的可維護(hù)性。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Filter;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.core.MessageSelector;
import org.springframework.integration.router.RecipientListRouter;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
@Configuration
public class FilterAndSelectiveRoutingConfig {
// 消息過濾器示例
@Bean
@Filter(inputChannel = "unfilteredChannel", outputChannel = "validOrderChannel")
public MessageSelector orderValidator() {
return message -> {
Order order = (Order) message.getPayload();
// 驗(yàn)證訂單是否有效
boolean isValid = order.getItems() != null && !order.getItems().isEmpty()
&& order.getCustomerId() != null
&& order.getTotalAmount() > 0;
return isValid;
};
}
// 結(jié)合過濾和路由的示例
@Bean
public org.springframework.integration.dsl.IntegrationFlow filterAndRouteFlow() {
return org.springframework.integration.dsl.IntegrationFlows
.from("inputOrderChannel")
// 首先過濾無效訂單
.filter(message -> {
Order order = (Order) message.getPayload();
return order.isValid();
})
// 然后根據(jù)訂單類型路由
.<Order, String>route(
order -> order.getType(),
mapping -> mapping
.subFlowMapping("RETAIL", sf -> sf.channel("retailOrderChannel"))
.subFlowMapping("WHOLESALE", sf -> sf.channel("wholesaleOrderChannel"))
.subFlowMapping("ONLINE", sf -> sf.channel("onlineOrderChannel"))
.defaultSubFlowMapping(sf -> sf.channel("unknownOrderChannel"))
)
.get();
}
// 使用RecipientListRouter實(shí)現(xiàn)有條件的多通道路由
@Bean
@Router(inputChannel = "orderRoutingChannel")
public RecipientListRouter orderRouter() {
RecipientListRouter router = new RecipientListRouter();
// 添加基于SpEL表達(dá)式的路由條件
router.addRecipient("highValueOrderChannel", "payload.totalAmount > 1000");
router.addRecipient("priorityCustomerOrderChannel", "payload.customerType == 'VIP'");
router.addRecipient("internationalOrderChannel", "payload.shippingAddress.country != 'China'");
// 將訂單同時(shí)發(fā)送到審計(jì)通道
router.addRecipient("orderAuditChannel");
return router;
}
// 處理無效訂單的示例
@Bean
@ServiceActivator(inputChannel = "invalidOrderChannel")
public void handleInvalidOrder(Message<Order> message) {
Order order = message.getPayload();
// 記錄無效訂單
System.out.println("無效訂單: " + order.getOrderId());
// 創(chuàng)建通知消息
Message<String> notification = MessageBuilder
.withPayload("訂單 " + order.getOrderId() + " 驗(yàn)證失敗")
.setHeader("notification-type", "ORDER_VALIDATION_FAILURE")
.setHeader("order-id", order.getOrderId())
.build();
// 發(fā)送通知
notificationChannel().send(notification);
}
@Bean
public org.springframework.messaging.MessageChannel notificationChannel() {
return new org.springframework.integration.channel.DirectChannel();
}
// 示例數(shù)據(jù)類
public static class Order {
private String orderId;
private String customerId;
private String customerType;
private String type;
private List<OrderItem> items;
private double totalAmount;
private Address shippingAddress;
// 省略getter和setter
public boolean isValid() {
return items != null && !items.isEmpty()
&& customerId != null
&& totalAmount > 0;
}
}
public static class OrderItem {
private String productId;
private int quantity;
private double price;
// 省略getter和setter
}
public static class Address {
private String street;
private String city;
private String state;
private String zipCode;
private String country;
// 省略getter和setter
}
}六、錯(cuò)誤處理與路由
在企業(yè)集成中,錯(cuò)誤處理是一個(gè)重要的考慮因素。Spring Integration提供了豐富的錯(cuò)誤處理機(jī)制,包括錯(cuò)誤通道、全局錯(cuò)誤處理器和特定組件的錯(cuò)誤處理配置。在路由過程中,可能會(huì)發(fā)生各種錯(cuò)誤,如無法找到匹配的通道、消息處理異常等。通過配置錯(cuò)誤通道和錯(cuò)誤處理器,可以在發(fā)生錯(cuò)誤時(shí)將消息路由到特定的錯(cuò)誤處理流程,從而實(shí)現(xiàn)錯(cuò)誤的集中處理和恢復(fù)。這種機(jī)制使得系統(tǒng)能夠更加健壯地應(yīng)對各種異常情況,提高了系統(tǒng)的可靠性和可用性。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer;
import org.springframework.integration.handler.advice.RequestHandlerRetryAdvice;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessagingException;
@Configuration
@IntegrationComponentScan
public class ErrorHandlingRouterConfig {
// 定義錯(cuò)誤通道
@Bean
public MessageChannel errorChannel() {
return new DirectChannel();
}
// 定義主路由器流程,包含錯(cuò)誤處理
@Bean
public IntegrationFlow routerWithErrorHandling() {
return IntegrationFlows
.from("inputChannel")
.<Message<?>, String>route(
message -> {
try {
// 從消息中提取路由鍵
String type = (String) message.getHeaders().get("message-type");
if (type == null) {
throw new IllegalArgumentException("消息類型不能為空");
}
return type;
} catch (Exception e) {
// 將異常信息放入消息頭
throw new MessagingException(message, "路由錯(cuò)誤: " + e.getMessage(), e);
}
},
mapping -> mapping
.subFlowMapping("ORDER", sf -> sf.channel("orderChannel"))
.subFlowMapping("INVENTORY", sf -> sf.channel("inventoryChannel"))
.defaultSubFlowMapping(sf -> sf.channel("unknownTypeChannel"))
)
// 配置錯(cuò)誤通道
.errorChannel("errorChannel")
.get();
}
// 錯(cuò)誤處理服務(wù)
@Bean
@ServiceActivator(inputChannel = "errorChannel")
public void handleError(Message<MessagingException> errorMessage) {
MessagingException exception = errorMessage.getPayload();
Message<?> failedMessage = exception.getFailedMessage();
System.err.println("處理消息時(shí)發(fā)生錯(cuò)誤: " + exception.getMessage());
System.err.println("失敗的消息: " + failedMessage);
// 根據(jù)異常類型執(zhí)行不同的錯(cuò)誤處理邏輯
if (exception.getCause() instanceof IllegalArgumentException) {
// 發(fā)送到無效消息通道
invalidMessageChannel().send(MessageBuilder
.withPayload(failedMessage.getPayload())
.copyHeaders(failedMessage.getHeaders())
.setHeader("error-message", exception.getMessage())
.build());
} else {
// 發(fā)送到重試通道,嘗試重新處理
retryChannel().send(failedMessage);
}
}
// 包含重試邏輯的路由器
@Bean
public IntegrationFlow retryableRouterFlow() {
return IntegrationFlows
.from("retryChannel")
.<Object, String>route(
payload -> {
if (payload instanceof Order) {
return "orderChannel";
} else if (payload instanceof InventoryItem) {
return "inventoryChannel";
} else {
return "unknownTypeChannel";
}
},
// 應(yīng)用重試通知
spec -> spec.advice(retryAdvice())
)
.get();
}
// 重試通知配置
@Bean
public RequestHandlerRetryAdvice retryAdvice() {
RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
// 配置重試策略
org.springframework.retry.support.RetryTemplate retryTemplate = new org.springframework.retry.support.RetryTemplate();
// 設(shè)置重試策略:最多重試3次
retryTemplate.setRetryPolicy(new org.springframework.retry.policy.SimpleRetryPolicy(3));
// 設(shè)置退避策略:指數(shù)退避,初始1秒,最大30秒
org.springframework.retry.backoff.ExponentialBackOffPolicy backOffPolicy = new org.springframework.retry.backoff.ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000);
backOffPolicy.setMaxInterval(30000);
backOffPolicy.setMultiplier(2.0);
retryTemplate.setBackOffPolicy(backOffPolicy);
advice.setRetryTemplate(retryTemplate);
// 設(shè)置恢復(fù)策略:發(fā)送到死信通道
ErrorMessageSendingRecoverer recoverer = new ErrorMessageSendingRecoverer(deadLetterChannel());
advice.setRecoveryCallback(recoverer);
return advice;
}
// 定義死信通道
@Bean
public MessageChannel deadLetterChannel() {
return new DirectChannel();
}
// 定義無效消息通道
@Bean
public MessageChannel invalidMessageChannel() {
return new DirectChannel();
}
// 定義重試通道
@Bean
public MessageChannel retryChannel() {
return new DirectChannel();
}
// 示例消息網(wǎng)關(guān)
@MessagingGateway(defaultRequestChannel = "inputChannel")
public interface MessageRoutingGateway {
void send(Message<?> message);
}
}總結(jié)
Spring Integration的Router組件為企業(yè)應(yīng)用集成提供了強(qiáng)大的消息路由能力,使得系統(tǒng)能夠根據(jù)不同的條件靈活地處理消息流。本文詳細(xì)介紹了Router的基礎(chǔ)概念、條件路由實(shí)現(xiàn)、基于消息頭的路由、動(dòng)態(tài)路由與路由表、消息過濾與選擇性路由以及錯(cuò)誤處理與路由等方面的內(nèi)容。這些技術(shù)為構(gòu)建復(fù)雜的企業(yè)集成解決方案提供了有力的支持,使得系統(tǒng)的各個(gè)組件能夠以松耦合的方式進(jìn)行協(xié)作,提高了系統(tǒng)的可維護(hù)性和可擴(kuò)展性。在實(shí)際應(yīng)用中,開發(fā)人員可以根據(jù)具體需求選擇合適的路由策略,通過組合使用多種路由機(jī)制,構(gòu)建靈活、健壯的消息處理流程。
到此這篇關(guān)于SpringIntegration消息路由之Router的條件路由與過濾的文章就介紹到這了,更多相關(guān)SpringIntegration消息路由內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于spring事務(wù)傳播行為非事務(wù)方式的理解
這篇文章主要介紹了對spring事務(wù)傳播行為非事務(wù)方式的全面理解,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
快速解決springboot在yml配置了啟動(dòng)端口但啟動(dòng)還是8080問題
這篇文章主要介紹了快速解決springboot在yml配置了啟動(dòng)端口但啟動(dòng)還是8080問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
關(guān)于JSqlparser使用攻略(高效的SQL解析工具)
這篇文章主要介紹了關(guān)于JSqlparser使用攻略(高效的SQL解析工具),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
使用迭代器模式來進(jìn)行Java的設(shè)計(jì)模式編程
這篇文章主要介紹了使用迭代器模式來進(jìn)行Java的設(shè)計(jì)模式編程,文中對迭代器模式中的容器封裝方面的知識(shí)進(jìn)行了講解,需要的朋友可以參考下2016-02-02
Project?Reactor源碼解析publishOn使用示例
這篇文章主要為大家介紹了Project?Reactor源碼解析publishOn使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
spring+maven實(shí)現(xiàn)發(fā)送郵件功能
這篇文章主要為大家詳細(xì)介紹了spring+maven實(shí)現(xiàn)發(fā)送郵件功能,利用spring提供的郵件工具來發(fā)送郵件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

