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

Swagger项目实战:新手入门教程

概述

本文详细介绍了Swagger项目实战的全部流程,包括环境搭建、API接口定义、文档生成、高级功能配置以及项目部署,帮助开发团队更高效地开发和维护API。通过规范化的API定义,Swagger能够自动生成API文档,使得API的开发和集成变得简单直观。Swagger项目实战涵盖了从开发到部署的每个环节,确保项目顺利进行。

Swagger简介与应用场景

Swagger是一个流行的开源框架,它提供了完整的功能集用于描述、生成、测试和可视化RESTful风格的Web服务。Swagger的前身是Swagger Specification,后来被Swagger Inc.开发。随着Apache 2.0许可的发布,Swagger Specification更名为OpenAPI Specification,Swagger Inc.被宣布为Apache 2.0授权的OpenAPI Initiative,一个由Linux Foundation支持的行业组织。

什么是Swagger

Swagger通过定义API接口的元数据来描述API接口。这使得API的文档生成、测试、可视化和实现自动化成为可能。它提供了Swagger UI,一种交互式的界面允许开发人员使用浏览器轻松地查看和测试API接口,这对于API的开发和集成非常有用。

Swagger的主要功能

  1. 定义API接口:Swagger使用OpenAPI规范定义API接口的结构,如操作、参数、响应等。
  2. 生成API文档:通过Swagger定义的API接口,可以自动生成API文档,包括交互式的API测试界面。
  3. 可视化API:Swagger UI能够可视化地展示API结构,使开发人员能够更直观地理解和使用API。
  4. API测试:通过Swagger UI,开发人员可以在实际实现之前测试API接口,确保它们按预期工作。
  5. 代码生成:Swagger提供了代码生成工具,可以根据定义的API接口生成客户端和服务器代码。
  6. 集成工具:Swagger支持与各种集成工具的集成,如Postman,GitHub等。

Swagger在项目中的应用场景

  1. API文档维护:Swagger能够自动生成API文档,这意味着维护API文档变得容易,降低了维护文档的工作量。
  2. API测试:开发人员可以使用Swagger UI测试API接口,确保它们按预期工作,这对于API的质量保证是非常重要的。
  3. API开发:Swagger提供了完整的API文档,包括API的示例,这有助于开发人员快速开发API。
  4. 团队协作:Swagger将API接口的定义与实现分离,使得团队可以专注于不同的部分,提高了团队的工作效率。
  5. API集成:Swagger提供了标准的API定义,使得不同系统之间可以很容易地集成。

Swagger是一个强大的工具,它能够在API开发的各个方面提供帮助,从定义API接口到测试API接口。

Swagger项目环境搭建

为了在项目中使用Swagger,需要完成一定的环境准备与配置。以下是具体的步骤:

开发环境准备

首先,需要确保开发环境已经配置好,并安装了必要的工具。在本教程中,我们将使用Spring Boot框架来集成Swagger,因此需要安装Java开发环境(JDK)、构建工具(如Maven或Gradle)以及一个IDE(如IntelliJ IDEA或Eclipse)。

  1. 安装Java环境:确保已安装JDK,版本8或以上。
  2. 安装构建工具:选择使用Maven或Gradle作为构建工具。
  3. 安装IDE:选择一个适合的IDE,如IntelliJ IDEA或Eclipse,并安装Spring Boot插件。
  4. 创建Spring Boot项目:使用Spring Boot插件创建一个新的Spring Boot项目。

以下是使用Maven创建Spring Boot项目的示例代码:

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>swagger-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

添加Swagger相关依赖

为了在Spring Boot项目中集成Swagger,需要添加Swagger的相关依赖。在pom.xml文件中添加如下依赖:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

这些依赖中,springfox-swagger2用于定义和生成Swagger文档,而springfox-swagger-ui用于提供Swagger UI,以便于展示和测试API。

配置Swagger的基本设置

配置Swagger的基本设置,包括启用Swagger,定义API的版本信息等。在Spring Boot中,可以通过创建一个配置类来完成这些设置。以下是一个示例配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .ignoredParameterTypes(Object.class)
                .build();
    }
}

在上述代码中,@EnableSwagger2注解用于启用Swagger功能,Docket对象用于定义Swagger的配置。通过RequestHandlerSelectors.any()PathSelectors.any()来选择所有的API接口和路径。此外,.ignoredParameterTypes(Object.class)用于忽略传递给Controller方法中的Object类型参数。

创建第一个Swagger文档

现在,我们已经准备好使用Swagger在Spring Boot项目中定义和生成API文档。本节将详细介绍如何定义API接口,生成Swagger文档,以及如何运行并查看Swagger UI。

定义API接口

首先,我们需要定义一个简单的API接口。这里假设我们有一个简单的RESTful API,它允许用户查询用户信息。以下是UserController的示例代码:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return new User(id, "John Doe");
    }
}

在这个示例中,定义了一个getUser方法,它通过路径参数id获取用户信息。User是一个简单的POJO类,这里简化为只包含idname两个字段:

public class User {
    private Long id;
    private String name;

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getter and Setter
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

使用注解生成Swagger文档

为了将定义的API接口转换为Swagger文档,我们使用Swagger注解来描述API接口的参数和响应。以下是UserController中定义的API接口的Swagger注解示例:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = "User API", description = "Operations on users", produces = "application/json")
public class UserController {

    @GetMapping("/users/{id}")
    @ApiOperation(value = "Get user by ID", notes = "Get user by id", response = User.class)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Success", response = User.class),
            @ApiResponse(code = 400, message = "Invalid input", response = Void.class),
            @ApiResponse(code = 404, message = "User not found", response = Void.class)
    })
    public User getUser(@ApiParam(value = "User ID", required = true) @PathVariable Long id) {
        return new User(id, "John Doe");
    }
}

在上述代码中,@Api注解用于描述整个控制器,@ApiOperation用于描述单个操作,@ApiParam用于描述路径参数或方法参数,@ApiResponses用于描述可能的响应。

运行并查看Swagger UI

现在我们已经定义并配置了Swagger文档,可以通过Swagger UI来查看和测试这些API接口。运行Spring Boot应用程序,然后在浏览器中访问http://localhost:8080/swagger-ui.html,你将看到Swagger UI界面,其中包含了我们定义的所有API接口。

Swagger UI会自动生成API文档,包括API接口的描述、参数、响应等。通过Swagger UI,开发人员可以直观地查看API文档,并通过提供的测试界面直接测试API接口。

常见注解与参数配置

在使用Swagger定义API接口时,会用到许多注解来描述接口的参数、响应等信息。本节将详细介绍这些注解,并解释如何使用它们来配置参数和响应。

API接口的常用注解

以下是Swagger中常用的注解,用于描述API接口:

  • @Api:用于描述控制器类。
  • @ApiOperation:用于描述单个操作。
  • @ApiParam:用于描述参数。
  • @ApiResponses:用于描述可能的响应。
  • @ApiResponse:用于描述单一的响应。

我们来看一个示例,定义一个API接口用于获取用户信息:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = "User API", description = "Operations on users", produces = "application/json")
public class UserController {

    @GetMapping("/users/{id}")
    @ApiOperation(value = "Get user by ID", notes = "Get user by id", response = User.class)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Success", response = User.class),
            @ApiResponse(code = 400, message = "Invalid input", response = Void.class),
            @ApiResponse(code = 404, message = "User not found", response = Void.class)
    })
    public User getUser(@ApiParam(value = "User ID", required = true) @PathVariable Long id) {
        return new User(id, "John Doe");
    }
}

参数类型与数据类型的定义

为了更好地描述API接口中的参数,可以使用@ApiParam注解来定义参数的类型、默认值、是否必填等信息。例如:

@ApiParam(value = "User ID", required = true)
@PathVariable Long id

在这里,value参数用于描述参数的含义,required参数用于指定该参数是否必须。

除了参数外,还可以使用@ApiModelProperty注解来定义响应对象中的字段。例如:

import io.swagger.annotations.ApiModelProperty;

public class User {
    @ApiModelProperty(value = "User ID", required = true, example = "123")
    private Long id;

    @ApiModelProperty(value = "User name", example = "John Doe")
    private String name;

    // Getter and Setter
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

通过这种方式,可以更详细地描述响应对象中的字段。

响应类型和示例的配置

使用@ApiResponse注解可以描述API操作的响应,包括响应状态码、消息和响应体的类型。例如:

@ApiResponse(code = 200, message = "Success", response = User.class)
@ApiResponse(code = 400, message = "Invalid input", response = Void.class)
@ApiResponse(code = 404, message = "User not found", response = Void.class)

这里定义了三种可能的响应情况,分别对应HTTP状态码200、400和404。response参数用于指定响应体的类型。

为了更详细地描述响应,可以使用examples参数来提供响应的示例。例如:

@ApiResponse(code = 200, message = "Success", response = User.class, examples = @Example(value = "{'id':123,'name':'John Doe'}"))

这里定义了一个200状态码的响应,并提供了一个响应体的示例。

Swagger文档的高级功能

除了基本的API定义和文档生成外,Swagger还提供了许多高级功能,包括安全认证配置、全局配置与分组管理、自定义UI样式与主题等。本节将详细介绍这些功能。

安全认证的配置

Swagger支持多种安全认证机制,如OAuth、API Key等。下面以OAuth认证为例,介绍如何在Swagger中配置安全认证。

在Swagger配置类中,可以通过securitySchemes方法来定义安全方案:

import springfox.documentation.builders.SecuritySchemeBuilder;
import springfox.documentation.service.SecurityScheme;
import java.util.Arrays;
import java.util.List;

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .securitySchemes(Arrays.asList(new SecuritySchemeBuilder()
                    .name("oauth2")
                    .build()))
            .securityContexts(Arrays.asList(SecurityContext.builder()
                    .securityReferences(Arrays.asList(new SecurityReference("oauth2", new AuthorizationScope[] {
                            new AuthorizationScope("global", "accessEverything")
                    }))
                    .build()))
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build();
}

在上述代码中,定义了一个名为oauth2的安全方案,并在securityContexts中指定了该安全方案。

在API接口定义中,可以通过@ApiResponses注解中的scopes参数来指定操作需要的安全范围:

@ApiOperation(value = "Get user by ID", notes = "Get user by ID", response = User.class,
        authorizations = @Authorization(value = "oauth2", scopes = {
                @AuthorizationScope(scope = "read", description = "read access"),
                @AuthorizationScope(scope = "write", description = "write access")
        }))
public User getUser(@PathVariable Long id) {
    return new User(id, "John Doe");
}

全局配置与分组管理

Swagger提供了全局配置和分组管理的功能,使得可以更好地组织和管理API接口。以下是如何配置全局设置和分组管理:

全局配置

全局配置可以定义Swagger UI的基本设置,如标题、描述等。可以在Swagger配置类中定义:

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build();
}

private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
            .title("Swagger Demo API")
            .description("This is a demo API for Swagger")
            .version("1.0.0")
            .build();
}

在上述代码中,定义了全局的标题、描述、版本等信息。

分组管理

分组管理允许将API接口按不同的组进行组织。可以通过groupName参数来指定接口所属的组:

@Bean
public Docket api1() {
    return new Docket(DocumentationType.SWAGGER_2)
            .groupName("Group 1")
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller.group1"))
            .paths(PathSelectors.any())
            .build();
}

@Bean
public Docket api2() {
    return new Docket(DocumentationType.SWAGGER_2)
            .groupName("Group 2")
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller.group2"))
            .paths(PathSelectors.any())
            .build();
}

在上述代码中,定义了两个组,分别包含不同包下的控制器。

自定义UI样式与主题

Swagger UI允许自定义UI样式和主题,以便更好地适应项目的需求。可以通过配置文件或直接修改Swagger UI的HTML和CSS来实现。

配置文件方式

在Swagger配置类中,可以通过uiConfiguration方法来定义UI配置:

@Bean
public UiConfiguration uiConfig() {
    return UiConfigurationBuilder.builder()
            .displayOperationId(true)
            .displayRequestDuration(true)
            .displayResponseExample(true)
            .build();
}

HTML和CSS方式

Swagger UI的HTML和CSS文件位于META-INF/resources/swagger-ui/index.htmlMETA-INF/resources/swagger-ui/swagger-ui.css。可以通过替换这些文件来自定义UI样式。

例如,替换index.html文件:

<!DOCTYPE html>
<html>
<head>
    <title>Swagger UI</title>
    <link rel="stylesheet" href="/swagger-ui/swagger-ui.css">
</head>
<body>
    <div id="swagger-ui"></div>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/swagger-ui/swagger-ui-bundle.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/swagger-ui/swagger-ui-standalone-preset.js"></script>
    <script>
        const ui = SwaggerUIBundle({
            url: "/v2/api-docs",
            dom_id: '#swagger-ui',
            deepLinking: true,
            presets: [
                SwaggerUIBundle.presets.apis,
                SwaggerUIBundle presets.standalone
            ],
            plugins: [
                SwaggerUIBundle plugins.oauth20Draft7
            ]
        });
    </script>
</body>
</html>

通过这种方式,可以自定义Swagger UI的样式和主题。

实战案例分享与项目部署

实际项目中的Swagger应用案例

假设我们正在为一个电商平台开发API接口,包括用户注册、登录、商品查询等功能。通过Swagger,我们可以定义和生成这些API接口的文档,确保开发人员能够顺利地开发和集成API接口。

用户注册API

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = "User API", description = "Operations on users", produces = "application/json")
public class UserController {

    @PostMapping("/users/register")
    @ApiOperation(value = "Register user", notes = "Register a new user", response = Void.class)
    @ApiResponses(value = {
            @ApiResponse(code = 201, message = "User registered", response = Void.class),
            @ApiResponse(code = 400, message = "Invalid input", response = Void.class)
    })
    public void registerUser(@RequestBody User user) {
        // User registration logic
    }
}

商品查询API

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = "Product API", description = "Operations on products", produces = "application/json")
public class ProductController {

    @GetMapping("/products/{id}")
    @ApiOperation(value = "Get product by ID", notes = "Get product by id", response = Product.class)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Success", response = Product.class),
            @ApiResponse(code = 400, message = "Invalid input", response = Void.class),
            @ApiResponse(code = 404, message = "Product not found", response = Void.class)
    })
    public Product getProduct(@ApiParam(value = "Product ID", required = true) @PathVariable Long id) {
        // Product retrieval logic
        return new Product(id, "Product Name");
    }
}

Swagger文档的维护与更新

Swagger文档的维护与更新对于确保API文档的准确性和时效性非常重要。以下是一些常见的维护与更新操作:

  1. 更新API接口定义:当API接口发生变化时,需要更新Swagger文档中的API接口定义,包括参数、响应等。
  2. 更新API接口的实现:当API接口的实现发生变化时,需要同步更新Swagger文档中的API接口定义。
  3. 定期审查和更新文档:定期审查和更新Swagger文档,确保文档的准确性和时效性。
  4. 使用版本控制:使用版本控制来管理Swagger文档的变更历史,以便于回溯和对比。

更新API接口定义

假设我们新增了一个API接口,用于更新用户信息。我们需要更新Swagger文档中的API接口定义:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = "User API", description = "Operations on users", produces = "application/json")
public class UserController {

    @PutMapping("/users/{id}")
    @ApiOperation(value = "Update user", notes = "Update user information", response = Void.class)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "User updated", response = Void.class),
            @ApiResponse(code = 400, message = "Invalid input", response = Void.class),
            @ApiResponse(code = 404, message = "User not found", response = Void.class)
    })
    public void updateUser(@PathVariable Long id, @RequestBody User user) {
        // User update logic
    }
}

在上述代码中,定义了一个updateUser方法,用于更新用户信息。

Swagger项目的部署与上线

部署Swagger项目到生产环境需要遵循一定的步骤,确保项目能够顺利运行并提供API文档。以下是如何部署Swagger项目的步骤:

  1. 构建项目:使用Maven或Gradle构建项目,生成可执行的JAR文件或WAR文件。
  2. 部署到应用服务器:将构建好的JAR文件或WAR文件部署到应用服务器,如Tomcat、Jetty等。
  3. 配置环境变量:根据需要配置环境变量,如数据库连接、日志级别等。
  4. 启动应用服务器:启动应用服务器,确保Swagger项目能够正常运行。
  5. 测试部署:通过访问Swagger UI来测试部署后的Swagger项目,确保所有API接口能够正常工作。
  6. 监控和维护:监控Swagger项目的运行状态,及时处理可能出现的问题。

构建项目

使用Maven构建项目,生成可执行的JAR文件:

mvn clean package

生成的JAR文件位于target目录下。

部署到应用服务器

将生成的JAR文件部署到应用服务器,如Tomcat。假设Tomcat安装在/opt/tomcat目录下,可以使用以下命令部署JAR文件:

cp target/swagger-demo.jar /opt/tomcat/webapps/swagger-demo.jar

配置环境变量

假设需要配置数据库连接,可以在application.properties文件中配置:

spring.datasource.url=jdbc:mysql://localhost:3306/swaggerdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

启动应用服务器

启动Tomcat应用服务器:

cd /opt/tomcat
./bin/startup.sh

测试部署

通过访问Swagger UI来测试部署后的Swagger项目,确保所有API接口能够正常工作。访问http://localhost:8080/swagger-ui.html,查看Swagger UI界面。

监控和维护

监控Swagger项目的运行状态,及时处理可能出现的问题。可以通过日志文件来监控项目运行状态:

tail -f /opt/tomcat/logs/catalina.out

通过以上步骤,可以顺利地将Swagger项目部署到生产环境,并确保其正常运行。

总结

通过本教程,我们学习了如何在Spring Boot项目中集成Swagger,并生成和维护API文档。我们介绍了Swagger的基本概念和应用场景,详细讲解了如何搭建Swagger开发环境,创建API接口,并生成Swagger文档。此外,我们还介绍了Swagger的高级功能,如安全认证配置、全局配置与分组管理、自定义UI样式与主题。最后,我们分享了实际项目中的Swagger应用案例,并介绍了Swagger项目的部署与上线步骤。

Swagger是一个强大的工具,能够帮助开发团队更高效地开发和维护API。通过规范化的API定义,Swagger能够自动生成API文档,使得API的开发和集成变得简单和直观。希望本教程能帮助读者更好地理解和使用Swagger。

点击查看更多内容
TA 点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消