当前位置:   article > 正文

快速上手Spring Cloud 九:服务间通信与消息队列_springcloud 服务通信

springcloud 服务通信

在这里插入图片描述

快速上手Spring Cloud 一:Spring Cloud 简介
快速上手Spring Cloud 二:核心组件解析
快速上手Spring Cloud 三:API网关深入探索与实战应用
快速上手Spring Cloud 四:微服务治理与安全
快速上手Spring Cloud 五:Spring Cloud与持续集成/持续部署(CI/CD)
快速上手Spring Cloud 六:容器化与微服务化
快速上手Spring Cloud 七:事件驱动架构与Spring Cloud
快速上手Spring Cloud 八:微服务架构中的数据管理
快速上手Spring Cloud 九:服务间通信与消息队列
快速上手Spring Cloud 十:Spring Cloud与微前端
快速上手Spring Cloud 十一:微服务架构下的安全与权限管理
快速上手Spring Cloud 十二:与云原生不得不说的故事

在微服务架构中,服务间通信是确保各组件协同工作、保持业务流畅运转的关键所在。而消息队列,作为一种高效、可靠的服务间通信方式,在Spring Cloud中扮演着举足轻重的角色。今天,我们就来深入探讨一下Spring Cloud与消息队列的集成,以及它们如何助力我们构建高性能、高可靠性的微服务应用。
在这里插入图片描述

1. Spring Cloud 与消息队列集成

在Spring Cloud中,我们可以轻松地将消息队列集成到微服务架构中,实现服务间的异步通信。其中,RabbitMQ和Kafka是两种非常流行的消息队列技术。

1.1 RabbitMQ 与 Kafka 在 Spring Cloud 中的集成方法

RabbitMQ 集成

要集成RabbitMQ,我们首先需要添加Spring Cloud Stream RabbitMQ Starter依赖。接下来,配置连接工厂、交换机、队列等关键组件。通过@EnableBinding注解,我们可以定义消息通道,并使用@Input@Output注解来标记消息的输入和输出通道。这样,我们就可以轻松地在服务间发送和接收消息了。

示例代码:

@EnableBinding(MyRabbitmqProducer.class)
public class RabbitmqProducer {

    @Autowired
    private MyRabbitmqProducer myRabbitmqProducer;

    public void send(String message) {
        myRabbitmqProducer.output().send(MessageBuilder.withPayload(message).build());
    }

    interface MyRabbitmqProducer {
        @Output("myQueue")
        MessageChannel output();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Kafka 集成

Kafka的集成过程与RabbitMQ类似。我们引入Spring Cloud Stream Kafka Starter,并配置Kafka集群地址、主题、序列化方式等。同样使用@EnableBinding注解来定义Kafka生产者和消费者,并通过消息通道实现消息的发送和接收。

示例代码:

@EnableBinding(MyKafkaProducer.class)
public class KafkaProducer {

    @Autowired
    private MyKafkaProducer myKafkaProducer;

    public void send(String message) {
        myKafkaProducer.output().send(MessageBuilder.withPayload(message).build());
    }

    interface MyKafkaProducer {
        @Output("myTopic")
        MessageChannel output();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1.2 消息队列在微服务架构中的角色与价值

消息队列在微服务架构中扮演着多重角色。首先,它作为中介实现了服务间的异步通信,降低了服务间的耦合度,使得服务可以更加独立地升级和扩展。其次,通过队列暂存消息,消息队列能够实现流量削峰,提高系统的稳定性。最后,消息队列还支持动态扩展服务实例,提高了系统的处理能力。
在这里插入图片描述

1.3 消息队列优缺点比较:RabbitMQ 与 Kafka 的适用场景

RabbitMQ:适用于实时性要求较高、消息量较小的场景。例如,订单处理、日志收集等。RabbitMQ的优点在于配置简单、易于管理;但在处理大量数据时,性能可能会受到限制。

Kafka:适用于大数据量、高吞吐量的场景。如日志分析、实时数据监控等。Kafka的优点在于高性能、高可靠性;但配置相对复杂,学习成本较高。

在这里插入图片描述

2. Spring Cloud中的异步通信:核心价值与应用探索

在微服务架构盛行的今天,异步通信成为了架构师和开发者们争相探索和实践的热门话题。尤其在Spring Cloud这一强大的微服务框架中,异步通信不仅提高了系统性能,还显著降低了服务间的耦合度,为业务的快速发展提供了有力支撑。

2.1 微服务架构中异步通信的重要性与优势

微服务架构的本质是将一个大型的复杂系统拆分成多个小型、独立的服务。这些服务之间通过轻量级的通信机制进行交互,以实现业务的协同。在这个过程中,异步通信显得尤为重要。

异步通信允许服务间不必相互等待,从而释放了系统的并发处理能力。在传统的同步通信模式下,一个服务的请求必须等待另一个服务的响应才能继续执行。而异步通信则打破了这种束缚,使得服务可以并行处理多个请求,大大提高了系统的吞吐量和响应速度。

此外,异步通信还实现了服务间的松耦合。松耦合意味着服务之间的依赖关系减少,每个服务都可以更加独立地运行和扩展。这种独立性不仅提高了系统的可维护性,还使得服务可以更加灵活地应对业务变化。

示例代码:使用Spring Cloud Stream实现异步消息传递

@EnableBinding(MyMessageChannels.class)
public class MyMessageProducer {

    @Autowired
    private MyMessageChannels myMessageChannels;

    public void sendMessage(String message) {
        myMessageChannels.output().send(MessageBuilder.withPayload(message).build());
    }
}

public interface MyMessageChannels {
    String OUTPUT = "myOutput";

    @Output(OUTPUT)
    MessageChannel output();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在上面的代码中,我们使用了Spring Cloud Stream来定义了一个消息生产者。通过@EnableBinding注解,我们绑定了自定义的消息通道接口MyMessageChannels。这个接口定义了一个输出通道output,用于发送消息。在sendMessage方法中,我们通过myMessageChannels.output().send()方法将消息发送到消息队列中。

2.2 异步通信如何提高系统性能与可伸缩性

异步通信通过减少服务间的等待时间,显著提高了系统的整体性能。在传统的同步通信模式下,一个服务的请求可能会因为等待另一个服务的响应而阻塞,导致资源的浪费和性能的下降。而异步通信则打破了这种阻塞,使得服务可以立即返回并处理其他请求,从而提高了系统的吞吐量和响应速度。

此外,异步通信还使得系统更加容易实现水平扩展。由于服务间的通信是异步的,我们可以根据业务需求动态地增加或减少服务实例。当业务量增加时,我们可以增加更多的服务实例来处理请求;当业务量减少时,我们可以减少服务实例以节省资源。这种灵活性使得系统能够轻松应对各种规模的业务需求。

2.3 异步通信在降低服务之间耦合度和响应时间上的作用

通过消息队列实现服务间的解耦是异步通信的一个重要应用。在微服务架构中,服务之间的直接依赖关系往往会导致耦合度的增加。当一个服务需要调用另一个服务时,它必须知道那个服务的地址、端口等信息,并且还需要处理可能的网络故障和超时等问题。这种依赖关系不仅增加了系统的复杂性,还使得服务的升级和维护变得更加困难。

而通过使用消息队列,我们可以将服务间的直接依赖关系转化为对消息队列的依赖。服务只需要将消息发送到队列中,然后由其他服务从队列中消费这些消息即可。这样,服务之间就不再需要直接通信,从而大大降低了耦合度。同时,由于消息队列具有缓冲和持久化的特性,它还可以帮助我们应对网络故障和超时等问题,提高系统的健壮性。

在响应时间方面,异步通信同样具有显著的优势。由于服务不需要等待其他服务的响应,因此可以大大减少整体响应时间。这对于需要快速响应的业务场景来说尤为重要。例如,在一个电商系统中,用户提交订单后需要等待支付系统的响应。如果使用同步通信模式,用户可能需要等待较长时间才能看到支付结果。而如果使用异步通信模式,系统可以立即返回一个支付中的状态给用户,并在后台异步处理支付逻辑,从而提高了用户体验。

异步通信在Spring Cloud微服务架构中发挥着举足轻重的作用。它不仅提高了系统性能和可伸缩性,还降低了服务之间的耦合度和响应时间。因此,在设计和开发微服务应用时,我们应该充分利用异步通信的优势,为业务的发展提供有力支撑。

在这里插入图片描述

3. 实现与优化高可靠性消息传递

在微服务架构中,消息传递扮演着举足轻重的角色,它连接着各个服务,确保数据的流动与同步。然而,在消息传递的过程中,如何确保消息的高可靠性,防止消息的丢失、重复或乱序,成为了我们必须要面对的挑战。在Spring Cloud中,通过一系列的配置和优化,我们可以实现高可靠性的消息传递。

3.1 高可靠性消息传递的关键挑战与解决方案

消息传递的过程中,我们可能会遇到诸多挑战。首先,消息可能会在传输过程中丢失,导致数据的不一致性。其次,消息可能会被重复发送,引发业务逻辑的重复执行。最后,消息的乱序也可能导致业务逻辑的混乱。

为了解决这些问题,我们可以采取以下策略:

  • 持久化队列:通过将消息持久化到磁盘或数据库中,确保即使消息队列服务宕机,消息也不会丢失。
  • 确保消息确认机制:在消息被成功处理后,发送方需要收到接收方的确认消息,以确保消息被正确处理。Spring Cloud提供了相应的确认机制,如RabbitMQ的ack确认模式。
  • 实现幂等性处理:对于可能被重复发送的消息,我们需要在业务逻辑上实现幂等性,即无论消息被发送多少次,业务逻辑的结果都是一致的。

示例代码:RabbitMQ的持久化队列与确认机制

@Configuration
public class RabbitMQConfig {

    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange("my-direct-exchange", true, false); // 持久化队列
    }

    @Bean
    public Queue myQueue() {
        return new Queue("my-queue", true); // 持久化队列
    }

    @Bean
    public Binding binding(Queue myQueue, DirectExchange directExchange) {
        return BindingBuilder.bind(myQueue).to(directExchange).with("my-routing-key");
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); // 设置手动确认模式
        return factory;
    }
}

@Service
public class MyMessageListener {

    @RabbitListener(queues = "my-queue")
    public void process(Message message, Channel channel) throws IOException {
        try {
            // 处理消息逻辑...
            // 确认消息已成功处理
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            // 处理异常,可能选择重新入队或记录日志等
            // 拒绝消息,可以选择是否重新入队
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

3.2 消息队列中消息传递的事务性保障与失败处理机制

在消息传递的过程中,事务性保障是至关重要的。通过确保消息的原子性操作,我们可以防止消息传递过程中出现不一致的状态。Spring Cloud支持消息队列的事务性操作,这意味着消息要么完全传递成功,要么完全失败,不会出现中间状态。

同时,为了处理消息传递失败的情况,我们需要实现一系列失败处理机制。例如,当消息传递失败时,我们可以选择重试发送消息,或者将消息发送到死信队列,以便后续处理。

示例代码:RabbitMQ的事务性发送

@Autowired
private RabbitTemplate rabbitTemplate;

public void sendMessageTransactional(final String exchange, final String routingKey, final Object message) {
    rabbitTemplate.execute(channel -> {
        channel.txSelect(); // 启动事务
        try {
            rabbitTemplate.convertAndSend(exchange, routingKey, message);
            channel.txCommit(); // 提交事务
        } catch (Exception e) {
            channel.txRollback(); // 发生异常时回滚事务
            throw e;
        }
        return null;
    });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3.3 优化消息队列配置与消息处理流程,确保高可靠性与性能

除了上述的可靠性保障措施,我们还需要对消息队列的配置和消息处理流程进行优化,以进一步提高可靠性和性能。

  • 调整队列大小与并发数:根据业务场景的需求,我们可以调整队列的大小和并发消费者数量,以平衡消息的吞吐量和处理延迟。
  • 简化消息处理逻辑:减少不必要的处理步骤和复杂度,可以降低系统的处理延迟,提高消息的处理速度。
  • 使用消息压缩:对于较大的消息,我们可以考虑使用压缩技术,减少消息的体积,从而提高网络传输效率。

示例代码:优化RabbitMQ消费者并发数

@RabbitListener(queues = "my-queue", concurrency = "10") // 设置并发消费者数量为10
public void process(Message message) {
    // 处理消息逻辑...
}
  • 1
  • 2
  • 3
  • 4

在Spring Cloud中实现高可靠性的消息传递是一个复杂而重要的任务。通过持久化队列、确保消息确认机制、实现幂等性处理,我们可以有效应对消息传递过程中的关键挑战。同时,利用消息队列提供的事务支持和失败处理机制,我们可以确保消息的原子性操作,并处理潜在的失败情况。最后,通过优化消息队列的配置和消息处理流程,我们可以进一步提高消息传递的可靠性和性能。

在实际应用中,我们需要根据具体的业务场景和需求,选择合适的策略和技术,并不断地监控和调整,以确保消息传递的高可靠性和高效性。随着技术的不断发展和微服务架构的广泛应用,相信我们会在高可靠性消息传递方面取得更多的进步和突破。

在这里插入图片描述

4. Spring Cloud与消息队列:实战案例与深度解析

在微服务架构的浪潮中,Spring Cloud凭借其卓越的集成能力和强大的功能,迅速成为业界的宠儿。而在实现微服务之间的通信与协作时,消息队列无疑是一个不可或缺的组件。今天,我们将结合具体的实战案例,深入探讨Spring Cloud与消息队列的完美结合,为您揭示其在实际项目中的应用和效果。

4.1 Spring Cloud与消息队列:携手共舞

在微服务架构中,服务之间的通信与协作至关重要。而Spring Cloud则为我们提供了一套完整的解决方案,其中消息队列扮演着举足轻重的角色。通过Spring Cloud与消息队列的集成,我们可以实现服务之间的异步通信、流量削峰、解耦等多种功能,从而大大提高系统的可靠性和效率。

4.2 电商项目实战:订单处理与库存更新的异步通信

让我们通过一个具体的电商项目案例,来探讨Spring Cloud与消息队列的应用。在这个项目中,我们使用了Spring Cloud和RabbitMQ来实现订单处理和库存更新的异步通信。

当用户提交订单时,订单服务会生成一个订单消息,并通过RabbitMQ的队列进行发送。库存服务则订阅了该队列,一旦接收到订单消息,就会进行相应的库存更新操作。这种异步通信的方式,使得订单服务和库存服务之间实现了松耦合,大大提高了系统的并发处理能力。

在Spring Cloud中,我们可以使用Spring Cloud Stream或Spring Integration等组件来简化消息队列的集成过程。以下是一个简单的示例代码,展示了如何使用Spring Cloud Stream与RabbitMQ进行集成:

@EnableBinding(Source.class)
public class OrderService {

    @Autowired
    private Source source;

    public void createOrder(Order order) {
        // 创建订单逻辑...

        // 发送订单消息到RabbitMQ队列
        source.output().send(MessageBuilder.withPayload(order).build());
    }
}

@EnableBinding(Sink.class)
public class InventoryService {

    @StreamListener(Sink.INPUT)
    public void handleOrder(Order order) {
        // 处理订单,更新库存逻辑...
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在上述代码中,OrderService负责创建订单并发送订单消息到RabbitMQ队列,而InventoryService则订阅了该队列并处理接收到的订单消息。通过这种方式,我们实现了订单处理和库存更新的异步通信。

4.3 日志收集系统的蜕变:Kafka的魔力

除了电商项目外,日志收集系统也是Spring Cloud与消息队列结合的另一个典型场景。在这个案例中,我们使用了Kafka作为日志收集系统的核心组件。

在整合Kafka之前,系统的日志处理存在严重的延迟和丢失问题。整合Kafka后,这些问题得到了有效的解决。Kafka的分布式、高吞吐、持久化的特性使得系统能够实时、可靠地处理大量的日志数据。

在Spring Cloud中,我们可以使用Spring Cloud Stream来简化Kafka的集成过程。通过定义输入和输出通道,我们可以轻松地实现日志数据的发送和接收。

4.4 最佳实践与经验分享

在项目实施过程中,我们总结了一些关于异步通信与高可靠性消息传递的最佳实践与经验。

首先,对于重要的消息传递场景,我们应该使用持久化队列来确保消息不会丢失。这可以通过配置消息队列的相关参数来实现。

其次,合理配置消息队列的并发数和重试机制也是提高系统处理能力和容错能力的关键。根据业务需求和系统负载情况,我们可以调整这些参数以达到最佳效果。

此外,对于复杂的业务场景,我们还可以考虑引入消息的顺序性保障和幂等性处理机制。这可以通过在消息中添加额外的元数据或使用特定的消息处理逻辑来实现。

总之,Spring Cloud与消息队列的结合为我们提供了强大的异步通信和消息传递能力。通过合理的配置和最佳实践的应用,我们可以实现高效、可靠的系统设计。在未来的项目中,让我们继续探索和实践,让Spring Cloud与消息队列的魔力为我们的业务赋能!

在这里插入图片描述

5. 深入探索:Spring Cloud与消息队列的集成细节

当我们谈到Spring Cloud与消息队列的集成时,我们不仅仅是在谈论简单的发送和接收消息。实际上,这种集成涉及到了多个层面和细节,如配置管理、错误处理、消息序列化等。

5.1 配置管理

在Spring Cloud中,我们可以使用配置文件(如application.yml或application.properties)来管理消息队列的相关配置。这包括连接信息(如主机名、端口号、用户名和密码等)、队列和交换器的名称、消息的序列化方式等。

通过Spring Cloud Config等配置中心,我们还可以实现配置的集中管理和动态刷新。这使得在多个微服务实例之间共享和更新消息队列配置变得非常容易。

示例代码:RabbitMQ配置

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener:
      simple:
        acknowledge-mode: manual # 手动确认模式
        concurrency: 5 # 并发消费者数量
        max-concurrency: 10 # 最大并发消费者数量
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

5.2 错误处理与重试机制

在消息传递过程中,可能会遇到各种错误,如网络故障、消息队列服务不可用等。为了确保消息的可靠传递,我们需要实现适当的错误处理和重试机制。

Spring Cloud Stream和Spring AMQP等组件为我们提供了强大的错误处理和重试支持。我们可以配置重试次数、重试间隔等参数,并在发生错误时执行相应的回退逻辑。

示例代码:消息发送失败处理

@Service
public class MessageSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(Message message) {
        try {
            rabbitTemplate.convertAndSend("exchangeName", "routingKey", message);
        } catch (AmqpException e) {
            // 处理发送失败的情况,如记录日志、重试等
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5.3 消息序列化与反序列化

消息的序列化和反序列化是消息传递过程中非常重要的环节。Spring Cloud支持多种序列化方式,如JSON、XML、Java序列化等。我们可以根据业务需求选择合适的序列化方式,并通过配置进行指定。

在Spring Cloud Stream中,我们可以通过在@Input@Output注解中指定contentTypeserializer等属性来配置序列化和反序列化方式。

5.4 高级特性与扩展

除了基本的发送和接收消息外,Spring Cloud还提供了许多高级特性和扩展功能,以满足更复杂的业务需求。例如,我们可以使用消息路由功能来实现消息的复杂分发逻辑;使用流量控制功能来限制消息的处理速率;使用安全认证功能来确保消息传递的安全性等。

Spring Cloud与消息队列的集成是微服务架构中实现异步通信和消息传递的关键环节。通过合理的配置和最佳实践的应用,我们可以实现高效、可靠的系统设计。随着技术的不断发展和业务的不断扩展,我们相信Spring Cloud与消息队列的结合将在未来发挥更大的作用,为企业的数字化转型提供强有力的支持。

在未来的实践中,我们将继续探索和研究Spring Cloud与消息队列的更多高级特性和应用场景,以不断提升系统的性能和可靠性。同时,我们也将关注新兴技术的发展趋势,如Apache Pulsar等新一代消息队列系统,以期为企业的业务发展提供更加强大的技术支撑。

6. 未来展望与发展趋势

6.1 消息队列技术在微服务架构中的未来地位与应用前景

随着微服务架构的日益成熟和广泛应用,消息队列技术在其中的角色和地位也愈发重要。在未来,消息队列技术将成为微服务架构中不可或缺的一部分,为服务的解耦、异步通信和流量削峰提供强大的支持。

在应用前景方面,随着企业业务的不断扩展和复杂化,消息队列将应用于更多场景,如实时数据分析、分布式事务处理、事件驱动架构等。此外,在物联网、边缘计算等新兴领域,消息队列也将发挥关键作用,助力实现设备间的高效通信和数据同步。

6.2 基于Spring Cloud的消息队列集成在未来的发展方向

Spring Cloud作为微服务架构的重要框架,其与消息队列的集成将在未来得到持续优化和增强。一方面,集成将更加全面和深入,覆盖更多主流的消息队列产品,提供更为丰富和灵活的配置选项。另一方面,集成将更加注重性能和稳定性,通过优化底层通信机制、提升并发处理能力等方式,确保消息传递的高效和可靠。

此外,基于Spring Cloud的消息队列集成还将朝着智能化和自动化的方向发展。通过引入人工智能和机器学习技术,实现对消息队列的智能监控、预警和调优,降低运维成本,提高系统的可用性和稳定性。

6.3 探讨异步通信与消息传递在未来系统设计中的创新应用和进步方向

异步通信与消息传递在未来系统设计中将呈现出更多的创新应用和进步方向。首先,在实时性方面,随着业务对实时性的要求越来越高,如何优化消息传递的延迟、提高实时处理能力将成为研究的重点。其次,在智能化管理方面,通过引入大数据分析、机器学习等技术,实现对消息队列的智能调度、负载均衡和故障预测,提升系统的自适应能力和稳定性。

此外,跨平台集成也将成为未来系统设计的一个重要方向。随着不同消息队列平台的不断涌现和发展,如何实现跨平台的无缝集成和互操作性将成为一个重要挑战。通过制定统一的标准和规范,推动不同平台之间的兼容和互通,将有助于提高系统的灵活性和可扩展性。

消息队列技术在微服务架构和基于Spring Cloud的集成中将继续发挥重要作用,并在未来系统设计中展现出更多的创新应用和进步方向。随着技术的不断发展和业务的不断扩展,我们有理由相信,消息队列技术将在未来迎来更加广阔的应用前景和发展空间。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/1007581
推荐阅读
相关标签
  

闽ICP备14008679号