为了账号安全,请及时绑定邮箱和手机立即绑定

SpringCloud应用项目实战:从入门到初级应用

标签:
Spring Cloud
概述

本文深入介绍了Spring Cloud应用项目实战,从Spring Cloud的基础概念、核心组件到微服务架构的搭建,内容涵盖了服务注册与发现、配置中心、服务网关等关键环节,旨在帮助开发者快速掌握Spring Cloud的使用方法。

Spring Cloud应用项目实战:从入门到初级应用
Spring Cloud简介

Spring Cloud是什么

Spring Cloud是一组开源框架的集合,旨在简化分布式系统中常见模式的实现,例如配置管理、服务发现、断路器、路由、微服务之间的调用以及客户端的负载均衡等。它建立在Spring Boot之上,利用Spring Boot的核心功能来快速构建独立运行、功能丰富的微服务应用。

Spring Cloud的核心概念

Spring Cloud中的核心概念包括服务注册与发现、配置中心、服务网关、负载均衡、断路器等。这些概念通过Spring Cloud提供的不同组件来实现,如Eureka、Config Server、Zuul、Ribbon、Hystrix等。

  • 服务注册与发现:通过服务注册与发现机制,微服务之间可以动态地找到彼此,实现服务的自动发现和负载均衡。
  • 配置中心:通过配置中心,可以集中管理微服务的配置文件,实现配置的版本控制和环境隔离。
  • 服务网关:服务网关作为微服务的统一入口,可以执行路由、过滤和安全操作。
  • 负载均衡:通过负载均衡组件可以实现请求的分散处理,提高系统性能和可用性。
  • 断路器:断路器组件可以在微服务之间实现容错机制,防止因某个服务故障导致整个系统崩溃。

Spring Cloud的优势

  • 简化开发:Spring Cloud提供了大量的解决方案,使得开发者能够快速搭建起微服务架构的应用。
  • 易于集成:Spring Cloud能够无缝集成各种第三方服务,如数据库、缓存、消息队列等。
  • 服务治理:通过服务注册与发现、负载均衡、断路器等机制,有效管理和治理微服务。
  • 配置管理:提供了集中式的配置管理服务,支持动态配置的推送。
  • 多种组件支持:Spring Cloud包括了众多组件,如服务注册与发现、配置中心、服务网关等,能够满足微服务开发的多种需求。
Spring Boot快速入门

Spring Boot的基本概念

Spring Boot是一个基于Spring框架的快速开发框架,它简化了Spring应用的配置,允许开发者通过最少的配置快速搭建功能完备的独立应用。Spring Boot的核心目标是简化新Spring应用的初始搭建以及开发过程,并且提供了一套完整的自动配置机制,使开发者能够专注于业务逻辑的实现,而无需过多关注底层配置细节。

创建第一个Spring Boot项目

创建一个简单的“Hello World” Spring Boot项目,演示如何使用Spring Boot进行快速开发。

步骤

  1. 创建一个新的Maven项目。
  2. 添加Spring Boot依赖。
  3. 编写Spring Boot启动类。
  4. 创建一个简单的控制器来返回“Hello World”。

代码实现

  1. 添加Spring Boot依赖
    pom.xml文件中添加Spring Boot的依赖。

    <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
    </dependencies>
  2. 编写Spring Boot启动类
    创建一个启动类,配置应用入口。

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DemoApplication {
       public static void main(String[] args) {
           SpringApplication.run(DemoApplication.class, args);
       }
    }
  3. 创建控制器
    创建一个简单的控制器来处理HTTP请求。

    package com.example.demo;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
       @GetMapping("/hello")
       public String sayHello() {
           return "Hello World";
       }
    }

运行应用

  1. 运行DemoApplication类中的main方法启动应用。
  2. 打开浏览器,访问http://localhost:8080/hello,页面显示“Hello World”。

Spring Boot项目的基本结构

Spring Boot项目的基本结构包括以下几个部分:

  • src/main/java:存放Java源代码,包含启动类和业务逻辑代码等。
  • src/main/resources:存放配置文件,如application.propertiesapplication.yml
  • src/test/java:存放测试代码。
  • pom.xml:Maven项目配置文件,用于管理依赖和构建配置。

项目目录示例

src
│── main
│   ├── java
│   │   └── com.example.demo
│   │       ├── DemoApplication.java
│   │       └── HelloController.java
│   └── resources
│       └── application.properties
└── test
    └── java
        └── com.example.demo
            └── DemoApplicationTests.java

通过以上步骤,可以快速搭建起一个Spring Boot应用,实现“Hello World”功能。Spring Boot简化了应用的配置和开发流程,使得开发者能够更加专注于业务逻辑的实现。

Spring Cloud微服务架构搭建

微服务架构介绍

微服务架构是一种将单体应用拆分成多个小型服务的架构模式。每个微服务负责实现一个特定功能,并通过定义良好的API接口与其他服务进行通信。微服务架构具有以下特点:

  • 模块化:将应用拆分成多个独立的微服务,每个微服务负责实现一个特定功能。
  • 独立部署:每个微服务可以独立部署和扩展,不受其他服务的影响。
  • 技术多样性:微服务可以使用不同的编程语言、框架和数据库,灵活选择最适合的技术栈。
  • 松耦合:微服务之间通过接口进行通信,降低了服务之间的耦合度。
  • 容错性:使用服务注册与发现、负载均衡、断路器等机制,提高系统的容错性和可用性。

微服务架构相对于传统的单体应用架构,具有更高的灵活性和可扩展性,能够更好地适应快速变化的业务需求。

使用Spring Cloud搭建微服务架构

使用Spring Cloud搭建微服务架构,可以通过以下步骤实现:

  1. 服务注册与发现:通过服务注册与发现机制,实现微服务之间的动态发现和通信。
    2.. 服务调用:使用Spring Cloud的负载均衡和断路器组件,实现服务之间的可靠调用。
  2. 配置管理:通过Spring Cloud的配置中心,集中管理微服务的配置文件,支持动态配置的推送。

示例1:服务注册与发现

使用Spring Cloud Eureka实现服务注册与发现。

  1. 添加依赖
    pom.xml文件中添加Eureka依赖。

    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
  2. 配置Eureka服务端
    application.properties文件中配置Eureka服务端的端口和其他参数。

    server.port=8761
    eureka.instance.hostname=localhost
    eureka.client.register-with-eureka=false
    eureka.client.fetch-registry=false
  3. 启动Eureka服务端
    创建启动类,配置Eureka服务端。

    package com.example.eurekaserver;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
       public static void main(String[] args) {
           SpringApplication.run(EurekaServerApplication.class, args);
       }
    }
  4. 启动Eureka服务端并访问
    运行启动类中的main方法启动Eureka服务端。
    http://localhost:8761/

示例2:服务调用

使用Spring Cloud Netflix Ribbon实现服务的负载均衡调用。

  1. 添加依赖
    在微服务客户端的pom.xml文件中添加Ribbon依赖。

    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
  2. 配置Ribbon客户端
    application.properties文件中配置Ribbon客户端的参数。

    eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
    spring.application.name=customer-service
  3. 创建Ribbon客户端
    创建一个Ribbon客户端,使用RestTemplate实现服务的调用。

    package com.example.customerservice;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class CustomerController {
       @Autowired
       @LoadBalanced
       private RestTemplate restTemplate;
    
       @Autowired
       private LoadBalancerClient loadBalancer;
    
       @GetMapping("/customers")
       public String getCustomers() {
           String url = loadBalancer.choose("order-service").getUri().toString() + "/orders";
           return restTemplate.getForObject(url, String.class);
       }
    }

通过以上步骤,可以使用Spring Cloud搭建起一个简单的微服务架构,实现服务注册与发现、服务调用等功能。

Spring Cloud服务网关API Gateway的实现

API Gateway的概念

API Gateway作为微服务架构中的统一入口,负责处理所有的客户端请求,并将请求分发到相应的服务。通过API Gateway,可以实现路由、过滤、身份验证、限流等操作,提高系统的灵活性和安全性。

使用Spring Cloud Gateway实现API Gateway

Spring Cloud Gateway是Spring Cloud的一套API Gateway解决方案,它基于Spring Boot 2.0、Spring WebFlux以及Project Reactor构建。通过Spring Cloud Gateway,可以实现服务路由、过滤器等功能。

示例1:创建Spring Cloud Gateway项目

  1. 创建一个新的Spring Boot项目
  2. 添加依赖
    pom.xml文件中添加Spring Cloud Gateway的依赖。

    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
  3. 配置Spring Cloud Gateway
    application.yml文件中配置路由规则。

    spring:
     application:
       name: api-gateway
    
    server:
     port: 8080
    
    spring.cloud.gateway.routes:
     - id: order-service
       uri: lb://order-service
       predicates:
         - Path=/order/**
     - id: customer-service
       uri: lb://customer-service
       predicates:
         - Path=/customer/**
  4. 启动Gateway服务
    创建一个启动类,配置Gateway服务。

    package com.example.apigateway;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class ApiGatewayApplication {
       public static void main(String[] args) {
           SpringApplication.run(ApiGatewayApplication.class, args);
       }
    }

示例2:添加过滤器

通过过滤器可以实现各种操作,如日志记录、请求修改等。

  1. 创建过滤器
    创建一个过滤器,实现对请求的处理。

    package com.example.apigateway.filter;
    
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    @Component
    @Order(-1)
    public class LoggingGatewayFilter implements GatewayFilter {
       @Override
       public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
           ServerHttpRequest request = exchange.getRequest();
           ServerHttpResponse response = exchange.getResponse();
    
           System.out.println("Request path: " + request.getPath());
           System.out.println("Request method: " + request.getMethod());
           System.out.println("Request headers: " + request.getHeaders());
    
           return chain.filter(exchange).then(Mono.fromRunnable(() -> {
               System.out.println("Response status: " + response.getStatusCode());
               System.out.println("Response headers: " + response.getHeaders());
           }));
       }
    }
  2. 配置过滤器
    application.yml文件中配置过滤器的使用。

    spring:
     application:
       name: api-gateway
    
    server:
     port: 8080
    
    spring.cloud.gateway.routes:
     - id: order-service
       uri: lb://order-service
       predicates:
         - Path=/order/**
       filters:
         - name: LoggingGatewayFilter

通过以上步骤,可以使用Spring Cloud Gateway搭建起一个简单的API Gateway,实现服务路由和过滤器功能。

实战案例:简单的订单系统

构建订单服务

订单服务是订单系统的核心部分,负责处理订单相关的操作,如创建订单、查询订单、更新订单等。

示例1:创建订单服务

  1. 创建一个新的Spring Boot项目
  2. 添加依赖
    pom.xml文件中添加Spring Web和Spring Data JPA依赖。

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
       <groupId>com.h2database</groupId>
       <artifactId>h2</artifactId>
       <scope>runtime</scope>
    </dependency>
  3. 配置数据库
    application.yml文件中配置H2数据库。

    spring:
     datasource:
       url: jdbc:h2:mem:testdb
       username: sa
       password:
     jpa:
       hibernate:
         ddl-auto: create-drop
       show-sql: true
       properties:
         hibernate:
           dialect: org.hibernate.dialect.H2Dialect
  4. 定义订单实体
    创建订单实体类,通过JPA实现数据库的持久化操作。

    package com.example.orderservice.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Order {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private Long id;
       private String orderId;
       private String customerId;
    
       // getter and setter
    }
  5. 创建订单仓库
    创建订单仓库类,实现对订单实体的数据库操作。

    package com.example.orderservice.repository;
    
    import com.example.orderservice.entity.Order;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface OrderRepository extends JpaRepository<Order, Long> {
    }
  6. 创建订单服务
    创建订单服务接口和实现类,实现对订单的操作。

    package com.example.orderservice.service;
    
    import com.example.orderservice.entity.Order;
    import com.example.orderservice.repository.OrderRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class OrderService {
       @Autowired
       private OrderRepository orderRepository;
    
       public Order createOrder(Order order) {
           return orderRepository.save(order);
       }
    
       public Order getOrderById(Long id) {
           return orderRepository.findById(id).orElse(null);
       }
    
       public Order updateOrder(Order order) {
           return orderRepository.save(order);
       }
    }
  7. 创建控制器
    创建订单控制器,实现对订单的HTTP操作。

    package com.example.orderservice.controller;
    
    import com.example.orderservice.entity.Order;
    import com.example.orderservice.service.OrderService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    public class OrderController {
       @Autowired
       private OrderService orderService;
    
       @PostMapping("/orders")
       public Order createOrder(@RequestBody Order order) {
           return orderService.createOrder(order);
       }
    
       @GetMapping("/orders/{id}")
       public Order getOrderById(@PathVariable Long id) {
           return orderService.getOrderById(id);
       }
    
       @PutMapping("/orders/{id}")
       public Order updateOrder(@PathVariable Long id, @RequestBody Order order) {
           order.setId(id);
           return orderService.updateOrder(order);
       }
    }

通过以上步骤,可以创建一个简单的订单服务,实现订单的创建、查询和更新操作。

构建商品服务

商品服务是订单系统中的一个模块,负责处理商品相关的操作,如查询商品信息、更新商品信息等。

示例2:创建商品服务

  1. 创建一个新的Spring Boot项目
  2. 添加依赖
    pom.xml文件中添加Spring Web和Spring Data JPA依赖。

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
       <groupId>com.h2database</groupId>
       <artifactId>h2</artifactId>
       <scope>runtime</scope>
    </dependency>
  3. 配置数据库
    application.yml文件中配置H2数据库。

    spring:
     datasource:
       url: jdbc:h2:mem:testdb
       username: sa
       password:
     jpa:
       hibernate:
         ddl-auto: create-drop
       show-sql: true
       properties:
         hibernate:
           dialect: org.hibernate.dialect.H2Dialect
  4. 定义商品实体
    创建商品实体类,通过JPA实现数据库的持久化操作。

    package com.example.productservice.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Product {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private Long id;
       private String productId;
       private String name;
       private Double price;
    
       // getter and setter
    }
  5. 创建商品仓库
    创建商品仓库类,实现对商品实体的数据库操作。

    package com.example.productservice.repository;
    
    import com.example.productservice.entity.Product;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface ProductRepository extends JpaRepository<Product, Long> {
    }
  6. 创建商品服务
    创建商品服务接口和实现类,实现对商品的操作。

    package com.example.productservice.service;
    
    import com.example.productservice.entity.Product;
    import com.example.productservice.repository.ProductRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class ProductService {
       @Autowired
       private ProductRepository productRepository;
    
       public Product createProduct(Product product) {
           return productRepository.save(product);
       }
    
       public Product getProductById(Long id) {
           return productRepository.findById(id).orElse(null);
       }
    
       public Product updateProduct(Product product) {
           return productRepository.save(product);
       }
    }
  7. 创建控制器
    创建商品控制器,实现对商品的HTTP操作。

    package com.example.productservice.controller;
    
    import com.example.productservice.entity.Product;
    import com.example.productservice.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    public class ProductController {
       @Autowired
       private ProductService productService;
    
       @PostMapping("/products")
       public Product createProduct(@RequestBody Product product) {
           return productService.createProduct(product);
       }
    
       @GetMapping("/products/{id}")
       public Product getProductById(@PathVariable Long id) {
           return productService.getProductById(id);
       }
    
       @PutMapping("/products/{id}")
       public Product updateProduct(@PathVariable Long id, @RequestBody Product product) {
           product.setId(id);
           return productService.updateProduct(product);
       }
    }

通过以上步骤,可以创建一个简单的商品服务,实现商品的创建、查询和更新操作。

订单服务与商品服务的集成

订单服务与商品服务的集成是订单系统的关键部分,通过服务调用实现订单与商品信息的交互。

示例3:订单服务调用商品服务

订单服务需要调用商品服务来获取商品信息,集成步骤如下:

  1. 添加依赖
    在订单服务的pom.xml文件中添加Spring Cloud Netflix Ribbon依赖。

    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
  2. 配置Ribbon客户端
    在订单服务的application.yml文件中配置Ribbon客户端的参数。

    eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
    spring.application.name=order-service
  3. 创建Ribbon客户端
    创建一个Ribbon客户端,使用RestTemplate实现对商品服务的调用。

    package com.example.orderservice;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class OrderController {
       @Autowired
       @LoadBalanced
       private RestTemplate restTemplate;
    
       @Autowired
       private LoadBalancerClient loadBalancer;
    
       @GetMapping("/orders/products/{productId}")
       public String getProduct(@PathVariable String productId) {
           String url = loadBalancer.choose("product-service").getUri().toString() + "/products/" + productId;
           return restTemplate.getForObject(url, String.class);
       }
    }

通过以上步骤,订单服务可以调用商品服务获取商品信息,实现订单与商品的集成。

Spring Cloud项目部署与运维

项目打包与部署

为了将Spring Cloud项目部署到生产环境,需要进行项目的打包、部署和配置。以下是详细的步骤:

示例1:项目打包

  1. 打包项目
    使用Maven或Gradle将项目打包成可执行的jar文件。

    mvn clean package
  2. 启动jar文件
    使用命令行启动打包后的jar文件。
    java -jar target/orderservice.jar

示例2:部署到Docker容器

使用Docker可以将项目打包成容器,简化部署和维护过程。

  1. 编写Dockerfile
    创建Dockerfile,定义容器的构建步骤。

    FROM openjdk:11-jre-slim
    COPY target/orderservice.jar orderservice.jar
    ENTRYPOINT ["java", "-jar", "orderservice.jar"]
  2. 构建Docker镜像
    使用Dockerfile构建镜像。

    docker build -t orderservice .
  3. 运行Docker容器
    使用命令行运行Docker容器。
    docker run -d -p 8080:8080 --name orderservice orderservice

通过以上步骤,可以将Spring Cloud项目打包成jar文件或Docker镜像,并部署到生产环境。

服务监控与日志管理

为了更好地管理和监控微服务应用,需要配置服务监控和日志管理功能。

示例1:服务监控

使用Spring Boot Actuator可以实现服务的监控功能。

  1. 添加依赖
    pom.xml文件中添加Spring Boot Actuator依赖。

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  2. 配置Actuator
    application.yml文件中配置Actuator的相关端点。

    management:
     endpoints:
       web:
         exposure:
           include: "*"
     endpoint:
       health:
         show-details: always
  3. 访问Actuator端点
    访问http://localhost:8080/actuator,查看服务的监控信息。

示例2:日志管理

使用Spring Boot的默认日志配置,可以实现日志的输出和管理。

  1. 配置日志
    application.yml文件中配置日志输出。

    logging:
     level:
       root: info
       com.example: debug
     file:
       name: ./logs/app.log
  2. 查看日志文件
    在项目根目录下查看生成的日志文件。

通过以上步骤,可以实现服务的监控和日志管理功能,更好地监控和管理微服务应用。

常见问题及解决方案

在Spring Cloud项目部署和运维过程中,可能会遇到一些常见问题,以下是一些典型的问题及解决方案。

问题1:服务注册失败

  • 原因:服务注册失败可能是因为服务没有正确配置服务注册中心的信息,或者服务注册中心出现问题。
  • 解决方案:检查服务的配置文件,确保服务注册中心的地址和端口正确。检查服务注册中心是否正常运行。

问题2:服务调用失败

  • 原因:服务调用失败可能是因为服务之间没有正确配置负载均衡和断路器,或者服务之间通信出现问题。
  • 解决方案:检查服务之间的配置,确保负载均衡和断路器配置正确。检查服务之间的网络通信是否正常。

问题3:服务监控失败

  • 原因:服务监控失败可能是因为Actuator端点配置不正确,或者服务监控插件没有正确启动。
  • 解决方案:检查Actuator端点的配置,确保端点暴露正确。确保服务监控插件正常启动。
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消