Swagger:构建与维护RESTful API文档指南

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Swagger是一种强大的API文档工具,它采用OpenAPI规范来标准化RESTful API的定义和文档化。它通过清晰的API描述,支持信息对象、路径对象、操作对象、参数对象、响应对象、模式对象和标签对象等核心组件,帮助开发者提升API的可读性、可维护性,并通过自动化测试和客户端库生成简化开发。Swagger的配置文件、示例和脚本工具等资源丰富了文档的内容,并通过Swagger UI增强了开发者体验。 Swagger-API-documentation

1. Swagger API文档的作用和优势

随着现代Web服务和微服务架构的流行,API文档的编写和维护变得越来越重要。Swagger API文档以其强大的功能和直观的用户体验,在众多API文档生成工具中脱颖而出。它不仅仅是静态文档,更是能够描述整个API的完整框架,让开发者能够快速上手和使用API。

Swagger允许开发团队以标准化的方式定义和描述API,通过自动生成的交互式文档,极大地改善了开发者的体验。它支持自动化测试,保证API的变化能够及时反映到文档中,从而降低了文档维护的工作量和出错的几率。

此外,Swagger的开放性使得它能够与多种开发工具和服务无缝集成,无论是前端开发者、后端开发者还是测试人员,都能在Swagger生态系统中找到适合自己的工具和资源,进而提高整个开发团队的工作效率。下一章我们将深入探讨OpenAPI规范,这是Swagger背后的标准和核心驱动力。

2. OpenAPI规范的应用

2.1 OpenAPI规范概述

2.1.1 OpenAPI规范的定义与背景

OpenAPI规范(OAS)是一个行业标准的接口描述语言,用于说明RESTful API。它让开发者和使用者能够在不了解后端实现细节的情况下理解和使用API。最初由Swagger项目团队创建,并于2015年捐献给Linux Foundation,成为了一个开源项目,即现在的OpenAPI Initiative(OAI)。OAS目前已经是实现API文档自动生成、API测试、API客户端代码生成等过程的行业标准。

2.1.2 OpenAPI规范的核心价值与演进

OpenAPI规范的核心价值在于它提供了一种结构化、标准化的方式定义API。这种方式使得API的设计可以被机器读取和处理,从而实现自动化处理。OAS通过一套简洁的YAML或JSON格式的定义文件,定义了操作、响应、身份验证方式等API元素,使得文档维护、团队协作和API消费者对API的理解变得更加容易。

从版本2.0到现在的3.0版本,OpenAPI规范进行了大量的演进,变得更加灵活、易于扩展。3.0版本引入了许多新特性,比如更丰富的数据类型、更好的安全性定义和对API版本的更好支持等。

2.2 OpenAPI规范在项目中的实际应用

2.2.1 设计与维护RESTful API的流程

在设计RESTful API时,首先需要创建一个OpenAPI规范的定义文件。这通常可以通过编辑YAML或JSON文件来完成,也可以利用一些图形界面工具,如Swagger Editor。定义文件包含API的路径、操作方法、请求和响应的数据结构等信息。

API设计完成后,可以使用OpenAPI工具集,如Swagger Codegen,自动生成服务器端的代码框架、客户端库、API文档等,极大地提高了开发效率。随着API的演进,只需更新OpenAPI定义文件,相关的代码和文档也会自动更新,确保了文档与代码的一致性。

2.2.2 如何通过OpenAPI规范提高API文档质量

OpenAPI规范不仅可以帮助维护API的定义,还可以极大地提高API文档的质量。使用规范定义文件,可以自动生成格式一致、内容全面的API文档。这有助于API的使用者快速理解API功能,减少学习成本。

此外,OpenAPI支持使用扩展属性来添加额外的信息,比如API的使用示例、错误码的具体说明等,使文档内容更加丰富和实用。通过这些手段,OpenAPI规范确保了API文档的高质量输出。

2.3 OpenAPI规范与行业标准的融合

2.3.1 OpenAPI规范与其他API描述语言的对比

OpenAPI规范作为业界最广泛使用的API描述语言,与其他规范如RAML、API Blueprint等存在一定的竞争关系。与RAML相比,OpenAPI更侧重于API的使用和消费方面,提供丰富的终端用户功能。而RAML则更加注重API的设计和文档化。

API Blueprint在语法上与Markdown相似,易于阅读和编写,但它不像OpenAPI那样广泛支持生成代码框架和客户端库。每种语言都有其优势和使用场景,而OpenAPI因其易用性和强大的生态系统而占据了一席之地。

2.3.2 行业案例分析:OpenAPI规范在实际业务中的应用

在实际业务中,许多大型企业和组织已经采用了OpenAPI规范,来确保其API的标准化和互操作性。例如,金融服务行业中的支付处理和交易API,通过使用OpenAPI规范,能够实现快速、标准化的API集成和文档化。

在零售行业,OpenAPI也被广泛应用于供应链管理和在线商店的API集成中,提高了API开发和维护的效率。此外,政府机构和服务提供商之间的数据共享也常常依赖于OpenAPI规范来确保信息的准确传递和高效沟通。

通过上述案例可以发现,OpenAPI规范已经成为API开发的重要基石,不仅在商业领域,在公共服务领域也发挥着巨大作用。随着技术的不断进步,OpenAPI规范将继续引领API开发的潮流,为各行各业提供标准化的解决方案。

3. API文档核心组件详解

在构建和维护RESTful API时,文档不仅是API提供者与使用者之间沟通的桥梁,而且是确保API质量和可用性的关键因素。一个良好的API文档应该详细说明API的工作原理以及如何正确使用它。本章节将深入探讨API文档的核心组件,并解释其背后的工作原理以及它们是如何被整合在一起,以创建出全面而准确的API文档。

3.1 API信息的定义

在API文档的创建过程中,首先需要定义关于API的高层次信息,包括API的概述、标签、外部文档等。这些信息对于了解API的目的和它的功能范围至关重要。

3.1.1 API的概述、标签和外部文档

API概述是描述API所实现功能的简短段落。这个概述为API文档的读者提供了第一印象,并帮助他们确定这个API是否满足他们的需求。标签(tags)则用于对API进行分类,以便用户可以根据功能或领域快速定位到相关的API部分。外部文档(externalDocs)则提供了指向更详细文档的链接,通常用于提供更多背景信息或补充材料。

示例代码块

openapi: 3.0.0
info:
  title: My API
  version: '1.0'
  description: API Description...
  contact:
    name: API Support
    url: http://www.example.com/support
    email: support@example.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
tags:
  - name: Users
    description: API operations about users
externalDocs:
  description: Find more info here
  url: https://example.com/api-docs

逻辑分析与参数说明

  • info 节是文档的顶级元素,用于描述API的基本信息。 title version 是其中的必填项。
  • description 提供了API的详细描述,可以为编写文档的开发人员提供指导。
  • contact 节为API的维护者提供了联系方式。
  • license 节用于指明API所使用的许可证。
  • tags 节用于对API进行分组,这有助于用户按功能快速浏览API。
  • externalDocs 提供了一个可选的链接,指向更详尽的外部文档。

3.1.2 API版本号的规范与实践

API版本号的管理是API生命周期中一个重要的环节。合理的版本号规划可以帮助开发人员和用户跟踪API的变更,以及决定何时迁移到新版本。通常API版本号采用语义化版本控制(Semantic Versioning),遵循主版本号.次版本号.修订号的格式。

规范说明

  • 主版本号(major):当你做了不兼容的API更改时。
  • 次版本号(minor):当你添加了向下兼容的新功能时。
  • 修订号(patch):当你做了向下兼容的问题修正时。

版本号实践

  • 在API路径中包含版本号:例如, /v1/users
  • 使用API网关或路由器来路由请求到正确的API版本。
  • 在更新API时,确保向后兼容性,以减少对现有客户端的影响。

3.2 API路径与操作

API路径与操作是API的核心组成部分,它们定义了API的资源以及如何通过HTTP方法对这些资源进行增删改查等操作。

3.2.1 定义API路径和方法

API路径定义了访问API资源的URL,而HTTP方法则定义了对资源的操作类型。在OpenAPI规范中,使用 paths 对象来定义这些元素。

示例代码块

paths:
  /users:
    get:
      summary: Returns a list of users
      responses:
        '200':
          description: An array of users
    post:
      summary: Creates a new user
      responses:
        '201':
          description: The created user
  /users/{id}:
    get:
      summary: Gets a user by ID
      parameters:
        - name: id
          in: path
          description: Unique ID of the user
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: A single user

逻辑分析与参数说明

  • paths 对象包含了API的路由信息。
  • get post 是HTTP方法,分别用于获取资源和创建新资源。
  • summary 为每个操作提供了简短的描述。
  • responses 对象定义了操作可能的返回状态码和它们对应的描述。

3.2.2 路径参数、查询参数与请求体的详细说明

在定义API操作时,路径参数、查询参数和请求体是传递数据给API的主要方式。路径参数通常用于标识唯一的资源,查询参数用于传递可选的数据筛选条件,请求体则用于提交需要创建或更新的数据。

路径参数 :以 /users/{id} 为例, id 是一个路径参数,它用于在请求URL中标识特定的用户。

查询参数 :例如, /users?role=manager 中的 role 参数就是一个查询参数,用于从数据库中筛选出具有“manager”角色的用户。

请求体 :在创建或更新资源时,通常需要提交一个JSON格式的请求体,包含资源的详细信息。

3.3 API安全与认证

在API的设计中,安全性是一个不可忽视的方面。API安全机制确保了只有授权用户才能访问敏感资源。

3.3.1 API安全机制的介绍

API安全机制主要包括以下几个方面:

  • 认证(Authentication):验证用户身份。
  • 授权(Authorization):确定用户是否有权访问特定资源。
  • 加密(Encryption):保护数据在传输过程中的安全。

认证方式

  • 基本认证(Basic Auth):用户必须提供用户名和密码。
  • API密钥:提供一个密钥来验证请求。
  • OAuth2.0:一种授权框架,允许第三方应用请求有限的访问权限。

3.3.2 OAuth2.0、API密钥等认证方式的应用实例

OAuth2.0 :

  • OAuth2.0是一种被广泛使用的授权协议。它允许第三方应用通过代表用户身份的令牌来请求API服务。
  • 在OpenAPI规范中,可以通过添加 security 字段来指定需要的认证方式。

API密钥 :

  • API密钥是生成和传递的字符串,用作访问限制API的密钥。
  • 在OpenAPI规范中,可以在 securitySchemes 字段中定义API密钥的安全机制,并在 security 字段中要求使用。

代码块示例:

securitySchemes:
  api_key:
    type: apiKey
    in: header
    name: X-API-Key
  oauth2:
    type: oauth2
    flows:
      implicit:
        authorizationUrl: https://example.com/oauth/authorize
        scopes:
          read: Grants read access
          write: Grants write access
      password:
        tokenUrl: https://example.com/oauth/token
        scopes:
          read: Grants read access
          write: Grants write access
security:
  - api_key: []
  - oauth2:
      - read
      - write

逻辑分析与参数说明

  • securitySchemes 定义了支持的安全机制类型,如 apiKey oauth2
  • security 指定了在执行API操作时,安全方案需要覆盖的范围。
  • in 指定了密钥的位置,可以是 header query cookie
  • name 指定实际传递密钥的字段名称。

在本节中,我们已经探讨了API文档的核心组件,包括API信息的定义、API路径与操作的详细说明以及API安全与认证方式的介绍。这些内容为构建一个高质量的API文档奠定了基础,并且对API的用户和开发人员都是至关重要的。接下来的章节将深入探讨Swagger的配置文件和资源目录结构,以及如何通过Swagger进行自动化测试和客户端库的生成。

4. Swagger配置文件与资源目录结构

在现代的微服务架构中,API文档的生成和维护是开发过程中的重要环节。Swagger作为一个流行的API文档生成工具,通过配置文件和资源目录的组织可以实现API文档的自动化和规范化。接下来,我们将深入探讨Swagger配置文件的组成以及如何合理地组织资源目录以提升维护效率。

4.1 Swagger配置文件的组成

Swagger配置文件是整个API文档自动生成过程中的核心,它定义了API接口的详细信息,包括路径、操作、参数以及响应等。该配置文件通常遵循OpenAPI规范,允许我们以机器可读的形式描述API。

4.1.1 核心配置文件解析

Swagger的核心配置文件通常是一个YAML文件,文件名常为 swagger.yaml openapi.yaml 。以下是一个简单的核心配置文件示例:

openapi: "3.0.0"
info:
  title: Example API
  version: 1.0.0
paths:
  /users:
    get:
      summary: Returns a list of users
      responses:
        '200':
          description: OK

这个配置文件定义了一个API的基本信息(如版本和标题),以及一个简单的用户列表获取接口。

4.1.2 配置文件中各部分的作用与配置方法

配置文件中包含多个部分,每部分都扮演着不同的角色:

  • openapi : 指定使用的OpenAPI规范的版本。
  • info : 提供API的基本信息,包括标题、描述、版本等。
  • paths : 定义API的端点和与之相关的操作。
  • responses : 描述API操作的可能响应。

每个操作(如GET、POST)下可以进一步定义:

  • summary : 操作的简短描述。
  • description : 更详细的操作描述。
  • parameters : 请求的参数。
  • responses : 描述操作的预期响应。

通过合理配置这些部分,可以确保生成的API文档既完整又易于理解。

4.2 资源目录的组织与结构

Swagger不仅仅是一个API文档生成工具,它还能够将API定义转换为客户端库或服务器端的代码。这一切的实现都依赖于资源目录的组织结构。

4.2.1 资源目录下的文件类型与作用

资源目录通常包含以下类型的文件:

  • Swagger定义文件 : 如前面所述的 swagger.yaml ,是定义API接口信息的核心文件。
  • 资源文件 : 包括API描述、模型定义和示例值等。
  • 代码生成模板 : 用于自动化生成客户端或服务器代码的模板文件。
  • 配置文件 : 控制Swagger工具的行为,如 swagger-codegen-config.yaml
  • 示例请求和响应 : 用于展示API调用的具体格式和预期结果。

4.2.2 如何合理组织资源目录以提升维护效率

为了提高维护效率,资源目录应该遵循一定的组织结构。以下是一个推荐的目录结构示例:

api-resources/
├── models/
│   ├── User.yaml
│   └── ...
├── paths/
│   ├── users.yaml
│   └── ...
├── templates/
│   ├── client/
│   └── server/
├── swagger.yaml
├── swagger-codegen-config.yaml
└── ...
  • models 文件夹存放API的数据模型定义。
  • paths 文件夹存放各个API端点的定义。
  • templates 文件夹存放代码生成模板。

保持清晰的目录结构可以使得开发人员快速定位到文件的位置,同时也便于版本控制。

4.3 配置文件的高级应用

通过配置文件,Swagger不仅能够生成基础的API文档,还可以实现更高级的文档控制功能。

4.3.1 使用配置文件控制API文档的显示与行为

配置文件中可以定义一些参数来控制API文档的生成行为,例如:

swagger-codegen:
  configOptions:
    dateLibrary: java8
    library: resttemplate

以上示例中, dateLibrary 参数指定了日期处理库,而 library 参数指定了生成代码时使用的库。

4.3.2 配置文件的扩展与自定义

Swagger配置文件支持扩展和自定义,允许开发者添加额外的插件或功能。例如,可以通过自定义模板来调整生成代码的风格或添加特定的业务逻辑。

通过以上配置文件与资源目录结构的分析,我们可以看到Swagger在API文档自动生成和维护方面的灵活性和强大功能。合理利用Swagger的高级配置能够帮助团队提升开发效率和文档质量,进而加速整个开发流程。

5. 自动化测试与客户端库生成

5.1 自动化测试的基本原理

5.1.1 自动化测试框架的介绍

自动化测试是指利用自动化测试工具,按照预定的测试计划执行测试用例,以确保软件产品或应用程序符合预定要求的过程。相比手动测试,自动化测试能大幅提高测试效率,降低重复工作带来的误差,并能够快速重复执行测试用例,确保软件在开发过程中的持续性和稳定性。

自动化测试框架为测试提供了标准化的执行环境,让测试用例的编写、组织、执行更加高效和一致。常用的自动化测试框架包括Selenium、JUnit、TestNG、Mocha等,这些框架有的面向Web应用,有的面向桌面应用或移动应用。

5.1.2 测试用例的设计与管理

设计测试用例是自动化测试过程中至关重要的一环。测试用例需要覆盖所有的业务流程,包括正常流程和异常流程,确保任何潜在的问题都能够被发现。

测试用例设计应该遵循以下原则:

  • 明确性 :每个测试用例的步骤和预期结果必须清晰明确,避免歧义。
  • 可重复性 :测试用例应该可以在相同的条件下重复执行。
  • 独立性 :每个测试用例应独立于其他测试用例,不应受其他测试用例执行结果的影响。
  • 可维护性 :随着应用程序的变更,测试用例也应容易地进行更新和维护。

测试用例的管理通常使用版本控制系统进行跟踪和维护,常用的工具有Git、SVN、TFS等。

5.2 利用Swagger进行自动化测试

5.2.1 Swagger测试代码的生成与配置

Swagger不仅可以用来生成API文档,还能根据API描述生成测试代码。这些测试代码可以集成到自动化测试框架中,提供自动化的API测试功能。

以Swagger Codegen为例,它可以自动生成服务器端和客户端的代码模板,包括测试代码。以下是生成测试代码的基本步骤:

  1. 安装Swagger Codegen。
  2. 准备API的Swagger描述文件(通常是 swagger.json swagger.yaml )。
  3. 使用Swagger Codegen命令行工具生成代码。

示例代码块展示如何生成测试代码:

swagger-codegen generate -i <API描述文件> -l <语言> -o <输出目录>

参数说明:

  • -i :输入的Swagger描述文件。
  • -l :选择的编程语言。
  • -o :生成代码的输出目录。

生成代码后,接下来需要根据生成的测试代码框架进行配置。配置通常包括环境变量的设置、服务端点的配置等。

5.2.2 测试执行与结果验证

配置完成后,就可以执行测试并验证API的正确性了。使用Swagger生成的测试代码通常会内嵌一些默认的测试用例,但根据实际情况,开发者可能还需要编写额外的测试用例以覆盖更复杂或特定的场景。

执行测试通常使用测试框架提供的命令,例如:

mvn test

对于结果验证,自动化测试框架通常会提供丰富的断言工具,可以用来验证响应状态、响应体、头部信息等是否符合预期。一旦发现不一致,框架会标记该测试为失败,并提供详细的错误信息帮助定位问题。

5.3 客户端库的生成与应用

5.3.1 自动生成客户端库的流程

客户端库是为方便客户端应用调用远程服务而生成的一组API接口封装。Swagger Codegen可以根据API的OpenAPI描述文件自动生成客户端库代码。开发者无需从零开始编写代码,即可快速集成API。

以下是生成客户端库的步骤:

  1. 准备API的Swagger描述文件。
  2. 使用Swagger Codegen命令行工具指定需要生成的目标语言和客户端库类型。
  3. 执行命令生成客户端库代码。

示例代码块展示如何生成客户端库代码:

swagger-codegen generate -i <API描述文件> -l <语言> -t <模板类型> -o <输出目录>

参数说明:

  • -l :指定生成代码的目标语言。
  • -t :指定生成客户端库的模板类型,如java、python等。
  • -o :指定生成代码的输出目录。

生成的代码通常包含API请求的封装、参数的序列化、响应的解析等功能。

5.3.2 客户端库的集成与使用技巧

成功生成客户端库后,需要将其集成到目标项目中。具体集成步骤依赖于所选的编程语言和项目构建工具。以Java为例,集成过程可能包括将生成的库文件添加到项目的依赖管理配置中。

集成完成后,开发人员需要编写调用远程API的代码。以下是一些使用客户端库的技巧:

  • 使用异步调用 :大多数客户端库支持异步调用,这样可以避免阻塞主线程。
  • 异常处理 :对网络请求进行异常处理,合理处理API响应错误。
  • 参数校验 :在发送请求前对参数进行校验,确保传递给API的数据是有效的。
  • 版本兼容 :保持客户端库与API服务端的版本兼容,避免因版本不一致导致的问题。

使用这些技巧可以提升客户端库的使用效率和稳定性。

6. Swagger UI工具的开发者体验提升

Swagger UI是Swagger项目中一个非常重要的组成部分,它将OpenAPI规范文件(如Swagger文件)转换成直观、可交互的API文档。通过Swagger UI,开发者可以直观地浏览API文档,测试API接口,从而显著提升开发和测试的效率。

6.1 Swagger UI的功能与优势

6.1.1 Swagger UI的界面与交互特点

Swagger UI的用户界面设计简洁直观,它将复杂的API信息以列表和分组的形式展示给用户,并允许开发者通过点击和填写表单的方式测试API。在最新版本的Swagger UI中,支持了动态主题切换和定制化设置,这使得用户体验更加丰富和个性化。

Swagger UI不仅提供了清晰的API描述,还支持了交互式的API测试。开发者可以通过输入必要的参数直接在Swagger UI上执行API调用,查看响应数据,这对于API的调试和验证非常有帮助。

6.1.2 Swagger UI如何提升API文档的易用性

Swagger UI通过以下方式提升了API文档的易用性:

  • 即时反馈 : 在Swagger UI中测试API时,开发者可以立即看到API的响应结果,这样可以快速验证API的正确性。
  • 动态展示 : API的入参和出参都可以动态展示,而且支持多种数据格式,如JSON、XML等。
  • 多语言支持 : Swagger UI支持多种语言,适应了不同国家开发者的使用习惯。
  • 安全性展示 : 对于需要认证的API,Swagger UI会展示如何配置安全机制,并允许开发者在UI中进行配置。

6.2 定制Swagger UI以满足个性化需求

6.2.1 修改和扩展Swagger UI的默认主题

Swagger UI允许开发者通过修改配置文件来自定义主题样式。开发者可以通过覆盖默认的CSS文件来自定义色彩方案、布局、字体等。同时,Swagger UI支持多种预设的主题包,开发者可以直接引入这些主题包,轻松地改变Swagger UI的外观。

// 自定义主题的示例代码
const ui = SwaggerUIBundle({
  url: "swagger.json", // 指向OpenAPI规范文件的路径
  dom_id: '#swagger-ui', // 容器ID
  deepLinking: true, // 支持深度链接
  presets: [
    SwaggerUIStandalonePreset,
    SwaggerUIThemeパーク
  ],
  plugins: [
    SwaggerUIBundle.plugins.DownloadUrl
  ],
  layout: "StandaloneLayout" // 自定义布局
});

6.2.2 添加自定义插件和脚本增强功能

Swagger UI支持使用JavaScript插件和脚本来扩展其功能。开发者可以根据自己的需求,编写自定义脚本或引入第三方插件,例如增加代码示例、集成API网关、自动化测试等。

// 自定义插件示例
ui.addPlugin(function() {
  // 自定义插件逻辑
});

6.3 实际案例分析:使用Swagger UI提升开发效率

6.3.1 案例介绍:大型项目的API文档管理

在大型项目中,API文档的管理和维护是一项艰巨的任务。一个案例是使用Swagger UI管理具有多个微服务的电商平台API文档。该项目涉及的API数量众多,每个服务的API都使用Swagger进行描述,并通过Swagger UI将所有API文档集成到一个统一的界面中。

6.3.2 效率提升的具体措施与成效评估

为提升效率,该项目采取了以下措施:

  • 集中式管理 : 将所有服务的Swagger文件统一管理,并利用工具将它们合并为一个总的OpenAPI规范文件。
  • 自动化文档生成 : 结合Jenkins持续集成流程,自动将代码变更同步到Swagger文件中。
  • 用户角色管理 : 通过设置不同的用户角色和权限,确保API文档的安全性和访问控制。
  • 定制化扩展 : 根据团队的开发习惯,对Swagger UI进行了多项定制化扩展,包括定制主题、增加快捷操作等。

成效评估显示,通过Swagger UI的使用,开发人员可以更快地熟悉和测试新的API接口,减少了文档查阅和环境搭建的时间。此外,文档的更新和传播变得更加高效,减少了沟通成本,显著提升了整个开发团队的工作效率。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Swagger是一种强大的API文档工具,它采用OpenAPI规范来标准化RESTful API的定义和文档化。它通过清晰的API描述,支持信息对象、路径对象、操作对象、参数对象、响应对象、模式对象和标签对象等核心组件,帮助开发者提升API的可读性、可维护性,并通过自动化测试和客户端库生成简化开发。Swagger的配置文件、示例和脚本工具等资源丰富了文档的内容,并通过Swagger UI增强了开发者体验。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值