SpringIntegration消息路由之Router的条件路由与过滤功能

2025-04-02 03:50

本文主要是介绍SpringIntegration消息路由之Router的条件路由与过滤功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理...

引言

在企业集成架构中,消息路由是一个至关重要的环节,它负责根据预定的规则将消息分发到不同的目标通道。Spring Integration作为企业集成模式的实现框架,提供了强大的Router组件来满足各种复杂的路由需求。Router可以根据消息的内容、消息头或其它条件,智能地决定消息的流向,从而使系统的各个组件能够专注于自己的核心功能,提高了系统的模块化程度和可维护性。本文将深入探讨Spring Integration中Router的实现方式和应用场景,特别是条件路由和消息过滤的相关技术,通过具体示例展示如何在实际项目中有效地使用这些功能。

一、Router基础概念

Router是Spring Integration中的核心组件之一,其主要职责是根据特定的条件将输入消息路由到一个或多个输出通道。通过Router,可以构建灵活的消息流,实现业务逻辑的动态分支处理。Spring Integration提供了多种类型的Router实现,包括PayloadTypeRouter、HeaderValueRouter、RecipientListRouter、ExpressionEvaLuatingRouter等,开发人员可以根据具体需求选择合适的Router类型。Router的工作原理是接收来自输入通道的消息,根据配置的路由规则评估消息,然后决定将消息发送到哪个或哪些输出通道。

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();
    }
    // 基础路由器实现
    @Bean
    @Router(inputChannel = "inputChannel")
    public String route(Message<?> message) {
        // 根据消息的不同类型路由到不同的通道
        Object payload = message.javascriptgetPayload();
        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());
        }
    }
    // 示例数据类
    public static class Order {
        private String orderId;
        // 其他字段省略
    }
    public static class InventoryItem {
        private String itemId;
        // 其他字段省略
    }
    public static class Customer {
        private String customerId;
        // 其他字段省略
    }
}

二、条件路由实现

条件路由是指根据消息内容或消息头信息中的特定条件,将消息路由到不同的目标通道。Spring Integration提供了多种方式来实现条件路由,包括使用SpEL表达式、Java DSL和基于注解的配置。ExpressionEvaluatingRouter允许使用SpEL表达式定义路由条件,使得复杂的路由逻辑可以通过简洁的表达式实现。通过条件路由,系统可以根据业务规则动态地决定消息的处理流程,例如根据订单金额将订单分为高优先级和普通优先级处理,或者根据客户类型提供不同级别的服务。

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表达式的条件路由器
    @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) {
        // 根据客户类型和信用评分路由
        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";
        }
    }
    // 示例数据类
    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;
        }
    }
}

三、基于消息头的路由

在企业集成场景中,消息头通常包含了重要的元数据,如消息类型、优先级、来源系统等信息,这些信息对于路由决策十分有用。HeaderValueRouter专门用于根据消息头的值进行路由,简化了基于消息头的路由配置。通过消息头路由,可以在不解析消息内容的情况下快速做出路由决策,提高了系统性能,同时也使得路由逻辑与业务逻辑分离,增强了系统的模块化程度。这种路由方式特别适合于处理来自不同系统的消息,或者需要根据消息的元数据进行分类处理的场景。

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");
        // 设置默认通道,当没有匹配的消息头值时使用
        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);
    }
    // 发送消息的示例方法
    public void sendMessage() {
        // 创建包含消息头的消息
        Message<String> orderMessage = MessageBuilder
                .withPayload("订单数据内容")
                .setHeader("message-type", "ORDER")
                .setHeader("priority", "HIGH")
                .build();
        Message<String> inventoryMessage = MessageBuilder
                .withPayload("库存数据内容")
                .setHeader("message-type", "INVENTORY")
                .setHeader("priority", "MEDIUM")
                .build();
        // 将消息发送到requestChannel,路由器会根据message-type头进行路由
        requestChannel().send(orderMessage);
        requestChannel().send(inventoryMessage);
    }
    @Bean
    public org.springframework.messaging.MessageChannel requestChannel() {
        return new org.springframework.integration.channel.DirectChannel();
    }
}

四、动态路由与路由表

在某些复杂的集成场景中,路由规则可能需要根据运行时的条件动态变化,或者需要在配置文件中定义而不是硬编码在代码中。Spring Integration提供了动态路由的能力,允许开发人员在运行时修改路由规则或从外部配置中加载路由表。AbstractMappingMessageRouter是实现动态路由的基础类,它维护了一个通道映射表,可以在运行时更新。这种方式使得系统能够适应业务规则的变化,而无需修改代码和重新部署,提高了系统的灵活性和可维护性。

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;
    // 自定义动态路由器
    @Bean
    @ServiceActivator(inputChanneandroidl = "dynamicRoutingChannel")
    public AbstractMappingMessageRouter dynamicRouter() {
        return new AbstractMappingMessageRouter() {
            @Override
            protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
                // 从服务中获取最新的路由规则
                Map<String, String> routingRules = routingRuleService.getRoutingRules();
                // 根据消息内容或头信息确定路由键
                String routingKey = extractRoutingKey(message);
                // 根据路由键查找目标通道名称
                String channelName = routingRules.getOrDefault(routingKey, "defaultChannel");
                // 获取目标通道并返回
                MessageChannel channel = getChannelResolver().resolveDestination(channelName);
                return Collections.singleton(channel);
            }
            private String extractRoutingKey(Message<?> message) {
                // 实现从消息中提取路由键的逻辑
                // 这里简化为从特定的消息头中获取
                return (String) message.getHeaders().get("routing-key");
            }
        };
    }
    // 路由规则服务,用于管理和提供路由规则
    @Bean
    public RoutingRuleService routingRuleService() {
        return new RoutingRuleService();
    }
    // 路由规则管理服务
    public static class RoutingRuleService {
        private Map<String, String> routingRules = new HashMap<>();
        public RoutingRuleService() {
            // 初始化默认路由规则
            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()));
        }
    }
    // 路由规则更新API
    @Bean
    @ServiceActivator(inputChannel = "routingRuleUpdateChannel")
    public void updateRoutingRule(Message<RoutingRuleUpdate> message) {
        RoutingRuleUpdate update = message.getPayload();
        routingRuleService.updateRoutingRule(update.getKey(), update.getChannelName());
    }
    // 路由规则更新请求
    public static class RoutingRuleUpdate {
        private String key;
        private String channelName;
        // 省略getter和setter
    }
}

五、消息过滤与选择性路由

消息过滤是路由的一种特殊形式,它基于特定条件决定是否允许消息继续流转。Spring Integration的Filter组件用于实现这一功能,它可以根据消息的内容或消息头信息过滤掉不符合条件的消息。过滤器可以作为独立的组件使用,也可以与路由器结合使用,实现更复杂的路由逻辑。例如,在处理订单消息时,可以过滤掉无效的订单,或者将不同类型的订单路由到不同的处理通道。这种选择性路由机制使得系统能够更有针对性地处理不同类型的消息,提高了处理效率和系统的可维护性。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Filter;
import org.springframework.integration.annotation.Rojavascriptuter;
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();
            // 验证订单是否有效
            boolean isValid = order.getItems() != null && !order.getItems().isEmpty()
                    && order.getCustomerId() != null
                    && order.getTotalAmount() > 0;
            return isValid;
        };
    }
    // 结合过滤和路由的示例
    @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();
                })
                // 然后根据订单类型路由
                .<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实现有条件的多通道路由
    @Bean
    @Router(inputChannel = "orderRoutingChannel")
    public RecipientListRouter orderRouter() {
        RecipientListRouter router = new RecipientListRouter();
        // 添加基于SpEL表达式的路由条件
        router.addRecipient("highValueOrderChannel", "payload.totalAmount > 1000");
        router.addRecipient("priorityCustomerOrderChannel", "payload.customerType == 'VIP'");
        router.addRecipient("internationalOrderChannel", "payload.shippingAddress.country != 'China'");
        // 将订单同时发送到审计通道
        router.addRecipient("orderAuditChannel");
        return router;
    }
    // 处理无效订单的示例
    @Bean
    @ServiceActivator(inputChannel = "invalidOrderChannel")
    public void handleInvalidOrder(Message<Order> message) {
        Order order = message.getPayload();
        // 记录无效订单
        System.out.println("无效订单: " + order.getOrderId());
        // 创建通知消息
        Message<String> notification = MessageBuilder
                .withPayload("订单 " + order.getOrderId() + " 验证失败")
                .setHeader("notification-type", "ORDER_VALIDATION_FAILURE")
                .setHeader("order-id", order.getOrderId())
                .build();
        // 发送通知
        notificationChannel().send(notification);
    }
    @Bean
    public org.springframework.messaging.MessageChannel notificationChannel() {
        return new org.springframework.integration.channel.DirectChannel();China编程
    }
    // 示例数据类
    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() {
   China编程         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
    }
}

六、错误处理与路由

在企业集成中,错误处理是一个重要的考虑因素。Spring Integration提供了丰富的错误处理机制,包括错误通道、全局错误处理器和特定组件的错误处理配置。在路由过程中,可能会发生各种错误,如无法找到匹配的通道、消息处理异常等。通过配置错误通道和错误处理器,可以在发生错误时将消息路由到特定的错误处理流程,从而实现错误的集中处理和恢复。这种机制使得系统能够更加健壮地应对各种异常情况,提高了系统的可靠性和可用性。

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 {
    // 定义错误通道
    @Bean
    public MessageChannel errorChannel() {
        return new DirectChannel();
    }
    // 定义主路由器流程,包含错误处理
    @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, "路由错误: " + e.getMessage(), e);
                            }
                        },
                        mapping -> mapping
                                .subFlowMapping("ORDER", sf -> sf.channel("orderChannel"))
                                .subFlowMapping("INVENTORY", sf -> sf.channel("inventoryChannel"))
                                .defaultSubFlowMapping(sf -> sf.channel("unknownTypeChannel"))
                )
                // 配置错误通道
                .errorChannel("errorChannel")
                .get();
    }
    // 错误处理服务
    @Bean
    @ServiceActivator(inputChannel = "errorChannel")
    public void handleError(Message<MessagingException> errorMessage) {
        MessagingException exception = errorMessage.getPayload();
        Message<?> failedMessage = exception.getFailedMessage();
        System.err.println("处理消息时发生错误: " + exception.getMessage());
        System.err.println("失败的消息: " + failedMessage);
        // 根据异常类型执行不同的错误处理逻辑
        if (exception.getCause() instanceof IllegalArgumentException) {
            // 发送到无效消息通道
            invalidMessageChannel().send(MessageBuilder
                    .withPayload(failedMessage.getPayload())
                    .copyHeaders(failedMessage.getHeaders())
                    .setHeader("error-message", exception.getMessage())
                    .build());
        } else {
            // 发送到重试通道,尝试重新处理
            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";
                            }
                        },
                        // 应用重试通知
                        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();
        // 设置重试策略:最多重试3次
        retryTemplate.setRetryPolicy(new org.springframework.retry.policy.SimpleRetryPolicy(3));
        // 设置退避策略:指数退避,初始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);
        // 设置恢复策略:发送到死信通道
        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();
    }
    // 示例消息网关
    @MessagingGateway(defaultRequestChannel = "inputChannel")
    public interface MessageRoutingGateway {
        void send(Message<?> message);
    }
}

总结

Spring Integration的Router组件为企业应用集成提供了强大的消息路由能力,使得系统能够根据不同的条件灵活地处理消息流。本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理与路由等方面的内容。这些技术为构建复杂的企业集成解决方案提供了有力的支持,使得系统的各个组件能够以松耦合的方式进行协作,提高了系统的可维护性和可扩展性。在实际应用中,开发人员可以根据具体需求选择合适的路由策略,通过组合使用多种路由机制,构建灵活、健壮的消息处理流程。

到此这篇关于SpringIntegration消息路由之Router的条件路由与过滤的文章就介绍到这了,更多相关SpringIntegration消息路由内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于SpringIntegration消息路由之Router的条件路由与过滤功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:http://www.cppcns.com/ruanjian/java/706243.html
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1154051

相关文章

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A

SpringCloud使用Nacos 配置中心实现配置自动刷新功能使用

《SpringCloud使用Nacos配置中心实现配置自动刷新功能使用》SpringCloud项目中使用Nacos作为配置中心可以方便开发及运维人员随时查看配置信息,及配置共享,并且Nacos支持配... 目录前言一、Nacos中集中配置方式?二、使用步骤1.使用$Value 注解2.使用@Configur

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

SpringCloud整合MQ实现消息总线服务方式

《SpringCloud整合MQ实现消息总线服务方式》:本文主要介绍SpringCloud整合MQ实现消息总线服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、背景介绍二、方案实践三、升级版总结一、背景介绍每当修改配置文件内容,如果需要客户端也同步更新,

SpringBoot后端实现小程序微信登录功能实现

《SpringBoot后端实现小程序微信登录功能实现》微信小程序登录是开发者通过微信提供的身份验证机制,获取用户唯一标识(openid)和会话密钥(session_key)的过程,这篇文章给大家介绍S... 目录SpringBoot实现微信小程序登录简介SpringBoot后端实现微信登录SpringBoo

使用Vue-ECharts实现数据可视化图表功能

《使用Vue-ECharts实现数据可视化图表功能》在前端开发中,经常会遇到需要展示数据可视化的需求,比如柱状图、折线图、饼图等,这类需求不仅要求我们准确地将数据呈现出来,还需要兼顾美观与交互体验,所... 目录前言为什么选择 vue-ECharts?1. 基于 ECharts,功能强大2. 更符合 Vue

Nginx路由匹配规则及优先级详解

《Nginx路由匹配规则及优先级详解》Nginx作为一个高性能的Web服务器和反向代理服务器,广泛用于负载均衡、请求转发等场景,在配置Nginx时,路由匹配规则是非常重要的概念,本文将详细介绍Ngin... 目录引言一、 Nginx的路由匹配规则概述二、 Nginx的路由匹配规则类型2.1 精确匹配(=)2

Java如何用乘号来重复字符串的功能

《Java如何用乘号来重复字符串的功能》:本文主要介绍Java使用乘号来重复字符串的功能,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java乘号来重复字符串的功能1、利用循环2、使用StringBuilder3、采用 Java 11 引入的String.rep

macOS Sequoia 15.5 发布: 改进邮件和屏幕使用时间功能

《macOSSequoia15.5发布:改进邮件和屏幕使用时间功能》经过常规Beta测试后,新的macOSSequoia15.5现已公开发布,但重要的新功能将被保留到WWDC和... MACOS Sequoia 15.5 正式发布!本次更新为 Mac 用户带来了一系列功能强化、错误修复和安全性提升,进一步增