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

Swagger学习:新手入门指南

概述

本文全面介绍了Swagger学习的相关内容,包括Swagger的基本概念、优势、应用场景以及如何安装和配置Swagger工具。文章详细讲解了编写Swagger文档的基本语法和实战演练,并提供了常见问题解答和学习资源推荐,帮助读者更好地理解和使用Swagger。从入门到实战,涵盖各个阶段,适合不同水平的开发者。

Swagger简介

Swagger 是一个开源的 API 建模框架,它能够帮助开发人员定义、构建、查看和测试 RESTful Web 服务。Swagger 定义了开放的 API 表达规范,使开发者能够更方便地描述和测试 API,同时也为前后端开发者提供了清晰的接口文档。

Swagger 的核心是 Swagger Spec,这是一种开源的 API 规范。它允许开发者使用简单明了的方式定义 REST API。Swagger Spec 必须包括 API 的基本信息,例如接口名称、版本、描述和每个接口的具体行为。通过这些信息,Swagger 可以自动生成 API 文档,文档不仅包括接口描述,还包括接口参数、返回值等详细信息。

Swagger 的优势包括:

  1. 易于理解:Swagger 提供的文档格式简单明了,易于理解和使用。
  2. 文档自动生成:通过 Swagger Spec,API 文档可以自动生成,减少了手工编写文档的工作量。
  3. 交互性强:Swagger 提供的在线文档不仅包括文字描述,还允许用户直接测试 API,提高文档的互动性。
  4. 兼容性强:Swagger 能够与多种语言和框架兼容,如 Java、Node.js、Python 等。
  5. 版本控制:Swagger 支持版本控制,不同版本的 API 可以并存,方便维护和迭代。

Swagger 主要应用于以下几个场景:

  1. API 设计和开发:Swagger 可以帮助开发人员快速定义和实现 API,提高了开发效率。
  2. API 测试:通过 Swagger 自动生成的文档,可以方便地测试 API 的行为和响应。
  3. API 文档生成:Swagger 自动创建的文档可以作为开发和调试的重要依据。
  4. API 文档分发:通过 Swagger,可以方便地将 API 文档分发给其他开发人员或终端用户。

安装与配置

安装Swagger工具

Swagger 提供了多种工具支持,包括 Swagger Editor、Swagger UI 和 Swagger Codegen。这些工具可以方便地帮助开发人员编写、测试和生成 API 文档。

  1. Swagger Editor:Swagger Editor 是一个在线的编辑器,用于编写 Swagger 文档,支持实时预览和语法检查。

    • 安装方法:访问 Swagger Editor 的官方网站,点击在线编辑器即可使用。
    • 使用方法:进入 Swagger Editor 后,你可以编写 Swagger 文档,并实时预览其效果。
  2. Swagger UI:Swagger UI 是一个用于展示 Swagger 文档的界面,用户可以通过 Web 界面查看和测试 API。

    • 安装方法:使用 Node.js 安装 Swagger UI:
      npm install -g @swagger-api/swagger-ui
    • 使用方法:在本地文件夹中安装 Swagger UI 后,可以使用以下命令启动 Swagger UI:
      swagger ui --help
      swagger ui --server "http://localhost:8080/swagger.json"
  3. Swagger Codegen:Swagger Codegen 是一个代码生成器,可以自动生成客户端、服务器端代码和文档。

    • 安装方法:使用 Maven 安装 Swagger Codegen:
      mvn package
      mvn install
    • 使用方法:使用 Swagger Codegen 生成代码:
      mvn swagger-codegen-cli:generate -DinputSpec=myapi.yaml -Dlanguage=java

配置Swagger文档

在配置 Swagger 文档时,需要在代码中引入 Swagger 的相关依赖,并通过注解配置 Swagger 的基本信息。

  1. 引入依赖:对于 Java Spring Boot 项目,需要在 pom.xmlbuild.gradle 中引入 Swagger 的依赖。

    • Maven 依赖:

      <dependency>
       <groupId>io.swagger</groupId>
       <artifactId>swagger-annotations</artifactId>
       <version>1.5.24</version>
      </dependency>
      <dependency>
       <groupId>io.swagger</groupId>
       <artifactId>swagger-models</artifactId>
       <version>1.5.24</version>
      </dependency>
      <dependency>
       <groupId>io.swagger</groupId>
       <artifactId>swagger-jaxrs</artifactId>
       <version>1.5.24</version>
      </dependency>
    • Gradle 依赖:
      implementation 'io.swagger:swagger-annotations:1.5.24'
      implementation 'io.swagger:swagger-models:1.5.24'
      implementation 'io.swagger:swagger-jaxrs:1.5.24'
  2. 配置 Swagger 注解:在 Java 代码中添加 Swagger 注解,定义 API 的基本信息。

    • 配置 Swagger 信息

      import io.swagger.annotations.Api;
      import io.swagger.annotations.ApiOperation;
      @Api(value = "User Controller", description = "Operations pertaining to users")
      public class UserController {
       @ApiOperation(value = "Retrieve a user", notes = "Returns a single user")
       public User getUser(Long id) {
           // 实现代码
       }
      }
    • 配置全局信息

      import io.swagger.annotations.ApiInfo;
      import io.swagger.annotations.SwaggerDefinition;
      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())
               .build()
               .apiInfo(apiInfo());
       }
      
       private ApiInfo apiInfo() {
           return new ApiInfo(
               "My API Documentation",
               "API documentation for my application",
               "1.0.0",
               "Terms of service",
               new Contact("John Doe", "http://johndoe.com", "admin@johndoe.com"),
               "License of API",
               "API license URL",
               Collections.emptyList()
           );
       }
      }
  3. 启动 Swagger UI:在 Spring Boot 中配置 Swagger UI 的启动。

    • 配置 Spring Boot 启动 Swagger UI

      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())
               .build();
       }
      }

通过以上步骤,可以成功安装并配置 Swagger 工具和文档,为后续的 API 开发和测试打下坚实的基础。

基础使用教程

编写Swagger文档的基本语法

Swagger 文档使用 YAML 或 JSON 格式编写,定义了 API 的基本信息和接口细节。以下是一个简单的 Swagger 文档示例,说明了如何定义 API 的基本信息。

  1. 定义全局基本信息:在 Swagger 文档的根节点中,可以定义全局的基本信息,包括 API 的标题、版本和描述等。

    • YAML 格式

      swagger: '2.0'
      info:
      title: API Documentation
      description: Documentation for our API
      version: 1.0.0
      host: api.example.com
      basePath: /api
      schemes:
      - https
      consumes:
      - application/json
      produces:
      - application/json
    • JSON 格式
      {
      "swagger": "2.0",
      "info": {
       "title": "API Documentation",
       "description": "Documentation for our API",
       "version": "1.0.0"
      },
      "host": "api.example.com",
      "basePath": "/api",
      "schemes": ["https"],
      "consumes": ["application/json"],
      "produces": ["application/json"]
      }
  2. 定义路径和操作:在 paths 节点下定义具体的 API 路径和操作,包括每个路径的 HTTP 方法(GET、POST、PUT 等),以及参数和响应信息。

    • YAML 格式

      paths:
      /users:
       get:
         summary: Get a list of users
         description: Returns a list of all users
         responses:
           200:
             description: A list of users
             schema:
               type: array
               items:
                 $ref: "#/definitions/User"
           401:
             description: Not authenticated
      /users/{id}:
       get:
         summary: Get a single user
         description: Returns a single user by ID
         parameters:
           - name: id
             in: path
             description: User ID
             required: true
             type: integer
             format: int64
         responses:
           200:
             description: A single user
             schema:
               $ref: "#/definitions/User"
           404:
             description: User not found
    • JSON 格式
      "paths": {
      "/users": {
       "get": {
         "summary": "Get a list of users",
         "description": "Returns a list of all users",
         "responses": {
           "200": {
             "description": "A list of users",
             "schema": {
               "type": "array",
               "items": {
                 "$ref": "#/definitions/User"
               }
             }
           },
           "401": {
             "description": "Not authenticated"
           }
         }
       }
      },
      "/users/{id}": {
       "get": {
         "summary": "Get a single user",
         "description": "Returns a single user by ID",
         "parameters": [
           {
             "name": "id",
             "in": "path",
             "description": "User ID",
             "required": true,
             "type": "integer",
             "format": "int64"
           }
         ],
         "responses": {
           "200": {
             "description": "A single user",
             "schema": {
               "$ref": "#/definitions/User"
             }
           },
           "404": {
             "description": "User not found"
           }
         }
       }
      }
      }
  3. 定义响应模式:在 definitions 节点中定义具体的响应模式,包括参数类型和结构。

    • YAML 格式

      definitions:
      User:
       type: object
       properties:
         id:
           type: integer
           format: int64
         name:
           type: string
         email:
           type: string
           format: email
         created_at:
           type: string
           format: date-time
    • JSON 格式
      "definitions": {
      "User": {
       "type": "object",
       "properties": {
         "id": {
           "type": "integer",
           "format": "int64"
         },
         "name": {
           "type": "string"
         },
         "email": {
           "type": "string",
           "format": "email"
         },
         "created_at": {
           "type": "string",
           "format": "date-time"
         }
       }
      }
      }

添加API信息和参数

  1. 添加 API 信息:在 Swagger 文档中,可以通过 tagsdescription 等参数来描述 API 的基本信息。

    • YAML 格式

      paths:
      /users:
       get:
         tags:
           - users
         summary: Get a list of users
         description: Returns a list of all users
         responses:
           200:
             description: A list of users
             schema:
               type: array
               items:
                 $ref: "#/definitions/User"
           401:
             description: Not authenticated
    • JSON 格式
      "paths": {
      "/users": {
       "get": {
         "tags": ["users"],
         "summary": "Get a list of users",
         "description": "Returns a list of all users",
         "responses": {
           "200": {
             "description": "A list of users",
             "schema": {
               "type": "array",
               "items": {
                 "$ref": "#/definitions/User"
               }
             }
           },
           "401": {
             "description": "Not authenticated"
           }
         }
       }
      }
      }
  2. 添加参数:在 Swagger 文档中,可以通过 parameters 节点定义请求中的参数,包括路径参数、查询参数、请求体参数等。

    • YAML 格式

      paths:
      /users/{id}:
       get:
         summary: Get a single user
         description: Returns a single user by ID
         parameters:
           - name: id
             in: path
             description: User ID
             required: true
             type: integer
             format: int64
         responses:
           200:
             description: A single user
             schema:
               $ref: "#/definitions/User"
           404:
             description: User not found
    • JSON 格式
      "paths": {
      "/users/{id}": {
       "get": {
         "summary": "Get a single user",
         "description": "Returns a single user by ID",
         "parameters": [
           {
             "name": "id",
             "in": "path",
             "description": "User ID",
             "required": true,
             "type": "integer",
             "format": "int64"
           }
         ],
         "responses": {
           "200": {
             "description": "A single user",
             "schema": {
               "$ref": "#/definitions/User"
             }
           },
           "404": {
             "description": "User not found"
           }
         }
       }
      }
      }

通过以上步骤,可以详细地定义 Swagger 文档的基本语法和接口信息,为后续的 API 开发和测试提供清晰的指导。

实战演练

创建简单的REST API接口文档

在这一部分,我们将创建一个简单的 REST API 接口文档,并通过 Swagger 展示和测试这些接口。

  1. 定义项目结构:首先,创建一个简单的 Spring Boot 项目,并组织项目结构如下:

    • src/main/java/com/example/api
    • src/main/resources
  2. 编写 API 接口:在 UserController 中定义一个简单的用户接口,包括获取用户列表和获取单个用户的接口。

    package com.example.api;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/api/users")
    public class UserController {
       @GetMapping("/")
       public List<User> getUsers() {
           // 实现代码
           return users;
       }
    
       @GetMapping("/{id}")
       public User getUserById(@PathVariable Long id) {
           // 实现代码
           return user;
       }
    }
  3. 编写 Swagger 文档:在 UserController 中添加 Swagger 注解,定义 API 的基本信息和参数。

    package com.example.api;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import io.swagger.annotations.ApiResponse;
    import io.swagger.annotations.ApiResponses;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/api/users")
    @Api(value = "User Controller", description = "Operations pertaining to users")
    public class UserController {
       @GetMapping("/")
       @ApiOperation(value = "Retrieve a list of users", notes = "Returns a list of all users")
       @ApiResponses(value = {
           @ApiResponse(code = 200, message = "Successful response"),
           @ApiResponse(code = 401, message = "Not authenticated")
       })
       public List<User> getUsers() {
           // 实现代码
           return users;
       }
    
       @GetMapping("/{id}")
       @ApiOperation(value = "Retrieve a single user", notes = "Returns a single user by ID")
       @ApiResponses(value = {
           @ApiResponse(code = 200, message = "Successful response"),
           @ApiResponse(code = 404, message = "User not found")
       })
       public User getUserById(@PathVariable Long id) {
           // 实现代码
           return user;
       }
    }
  4. 配置 Swagger UI:在 SwaggerConfig 类中配置 Swagger UI 的启动。

    package com.example.config;
    
    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())
                   .build();
       }
    }

测试和调试Swagger文档

在前面的步骤中,我们已经编写了 Swagger 文档并配置了 Swagger UI,接下来可以通过 Swagger UI 测试和调试这些 API 接口。

  1. 启动应用程序:运行 Spring Boot 应用程序。

    mvn spring-boot:run
  2. 访问 Swagger UI:启动应用程序后,在浏览器中访问 http://localhost:8080/swagger-ui.html,可以看到 Swagger UI 的界面。

    • 在 Swagger UI 界面中,可以看到定义的 API 接口列表和接口的详细信息。
  3. 测试 API 接口:点击具体的接口,可以看到接口的详细信息,包括请求方法、请求参数、示例请求等。通过点击“Try it out”按钮,可以直接测试接口。

    • 测试 getUsers 接口
      • 点击 getUsers 接口,可以看到接口的详细信息。
      • 点击“Try it out”按钮,可以看到接口的请求和响应示例。
    • 测试 getUserById 接口
      • 点击 getUserById 接口,可以看到接口的详细信息。
      • 输入路径参数 id,点击“Try it out”按钮,可以看到接口的请求和响应示例。

为了更全面地指导读者进行实际测试和调试,这里提供一个具体的测试用例:

package com.example.api;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@SpringBootTest
public class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetUsers() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/users"))
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andExpect(MockMvcResultMatchers.content().contentType("application/json"))
               .andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(10));
    }

    @Test
    public void testGetUserById() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/users/1"))
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andExpect(MockMvcResultMatchers.content().contentType("application/json"))
               .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1));
    }
}

通过以上步骤,可以有效地测试和调试 Swagger 文档定义的接口,确保 API 的正确性和可用性。

常见问题解答

Swagger使用中的常见问题

在使用 Swagger 过程中,开发者可能会遇到一些常见问题,以下是一些典型的常见问题和解决方案:

  1. Swagger 文档未加载

    • 问题:启动应用程序后,访问 Swagger UI 界面时,Swagger 文档未加载或显示错误信息。
    • 原因:可能是因为 Swagger 配置不正确,或者依赖库版本不匹配。
    • 解决方案
      • 检查 Swagger 的依赖库是否正确引入。
      • 检查 Swagger 配置类是否正确配置。
      • 确保 Swagger UI 的路径配置正确。
    • 示例代码
      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {
       @Bean
       public Docket api() {
           return new Docket(DocumentationType.SWAGGER_2)
                   .select()
                   .apis(RequestHandlerSelectors.any())
                   .paths(PathSelectors.any())
                   .build();
       }
      }
  2. Swagger 文档生成不完整

    • 问题:Swagger 文档未包含所有定义的接口或参数。
    • 原因:可能是因为 Swagger 注解未正确使用,或者资源类未被扫描到。
    • 解决方案
      • 确保所有 API 接口都使用了 Swagger 注解。
      • 检查资源类是否在 Swagger 配置中正确扫描。
    • 示例代码
      @RestController
      @RequestMapping("/api/users")
      @Api(value = "User Controller", description = "Operations pertaining to users")
      public class UserController {
       @GetMapping("/")
       @ApiOperation(value = "Retrieve a list of users", notes = "Returns a list of all users")
       public List<User> getUsers() {
           // 实现代码
           return users;
       }
      }
  3. Swagger UI 无法访问

    • 问题:启动应用程序后,访问 Swagger UI 界面时,无法打开或显示空白页面。
    • 原因:可能是因为 Swagger UI 的端口配置不正确,或者浏览器缓存导致的问题。
    • 解决方案
      • 检查 Swagger UI 的启动路径是否正确。
      • 清除浏览器缓存,尝试重新访问 Swagger UI。
      • 确保 Swagger UI 的路径配置正确。
    • 示例代码
      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {
       @Bean
       public Docket api() {
           return new Docket(DocumentationType.SWAGGER_2)
                   .select()
                   .apis(RequestHandlerSelectors.any())
                   .paths(PathSelectors.any())
                   .build();
       }
      }
  4. Swagger 文档与实际 API 不一致
    • 问题:Swagger 文档中的接口信息与实际运行的 API 不一致。
    • 原因:可能是因为 Swagger 注解未正确更新,或者接口实现未正确更新。
    • 解决方案
      • 确保 Swagger 注解与接口实现一致。
      • 检查接口实现是否有修改。
      • 重新构建和启动应用程序。
    • 示例代码
      @RestController
      @RequestMapping("/api/users")
      @Api(value = "User Controller", description = "Operations pertaining to users")
      public class UserController {
       @GetMapping("/")
       @ApiOperation(value = "Retrieve a list of users", notes = "Returns a list of all users")
       public List<User> getUsers() {
           // 实现代码
           return users;
       }
      }

解决方案和技巧

在解决 Swagger 使用中的常见问题时,可以采用以下一些解决方案和技巧:

  1. 使用在线编辑器

    • 好处:Swagger Editor 提供了在线编辑器,方便编写和预览 Swagger 文档。
    • 技巧:在 Swagger Editor 中编辑 Swagger 文档时,可以实时预览文档效果,快速发现和修正错误。
    • 示例
      swagger: '2.0'
      info:
      title: API Documentation
      description: Documentation for our API
      version: 1.0.0
  2. 调试 Swagger 文档

    • 好处:使用 Swagger UI 进行调试可以快速测试和验证 API 接口。
    • 技巧:在 Swagger UI 中,可以通过“Try it out”按钮直接测试接口,查看请求和响应结果。
    • 示例
      paths:
      /users:
       get:
         summary: Get a list of users
         description: Returns a list of all users
         responses:
           200:
             description: A list of users
             schema:
               type: array
               items:
                 $ref: "#/definitions/User"
           401:
             description: Not authenticated
  3. 版本控制

    • 好处:Swagger 支持版本控制,可以方便地管理和迭代不同的 API 版本。
    • 技巧:在 Swagger 文档中,可以通过版本号管理和区分不同的 API 版本。
    • 示例
      info:
      title: API Documentation
      description: Documentation for our API
      version: 1.0.0
  4. 代码生成器
    • 好处:Swagger Codegen 可以自动生成客户端、服务器端代码和文档。
    • 技巧:利用 Swagger Codegen 可以快速生成代码,减少手动编写的工作量。
    • 示例
      mvn swagger-codegen-cli:generate -DinputSpec=myapi.yaml -Dlanguage=java

通过以上解决方案和技巧,可以有效地解决 Swagger 使用中的常见问题,提高开发效率和文档质量。

学习资源推荐

Swagger官方文档

Swagger 官方文档是学习和使用 Swagger 的重要资源之一。它提供了详细的教程和 API 参考,帮助开发者快速上手和深入学习 Swagger。

在线教程和社区资源

除了官方文档外,还有很多在线教程和社区资源可以帮助开发者学习和使用 Swagger。

  1. 慕课网

    • 平台地址https://www.imooc.com/
    • 推荐课程
      • 《Swagger API 文档编写与测试》:该课程详细介绍了 Swagger 的基本概念和使用方法,适合新手入门。
      • 《Spring Boot 集成 Swagger 实战教程》:该课程通过实例演示了如何在 Spring Boot 项目中集成 Swagger,并编写和测试 API 文档。
    • 课程特点:课程内容详尽,包含理论讲解和实践操作,适合初学者和进阶开发者。
  2. Stack Overflow

    • 平台地址https://stackoverflow.com/
    • 推荐问题
      • 如何在 Spring Boot 中使用 Swagger?:该问题详细讨论了如何在 Spring Boot 项目中集成 Swagger,并提供了配置示例。
      • Swagger 文档未加载怎么办?:该问题提供了解决 Swagger 文档未加载的常见问题的解决方案。
    • 社区特点:Stack Overflow 是一个活跃的技术问答社区,提供丰富的技术问题解答和解决方案。
  3. GitHub
    • 平台地址https://github.com/
    • 推荐项目
      • Swagger UI:该项目提供了 Swagger UI 的源代码和示例,可以参考和学习。
      • Swagger Codegen:该项目提供了 Swagger Codegen 的源代码和使用示例,可以帮助开发者生成代码。
    • 项目特点:GitHub 是一个开源社区,提供了丰富的开源项目和示例,适合开发者深入学习和实践。

通过以上推荐的学习资源,可以系统地学习和掌握 Swagger 的使用方法,提高 API 开发和文档编写的能力。

点击查看更多内容
TA 点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消