Table of Contents Introduction First Chapter

Size: px
Start display at page:

Download "Table of Contents Introduction First Chapter"

Transcription

1 Table of Contents First Chapter

2 如何编写基于 OpenAPI 规范的 API 文档 [TOC] 前言编写目的 本文介绍如何使用 Swagger 编写 API 文档 通过阅读本文, 你可以 : 了解 swagger 是什么掌握使用 swagger 编写 API 文档的基本方法 涉及范围 本文包括对 swagger specification( 以下译作 规范 ) 的介绍, 如何使用 swaager 协议编写出功能完整 结构清晰的 API 文档, 以及项目实践中需要注意的问题 swagger 的生态完整, 从文档生成 编辑 测试到各种语言的代码自动生成, 都有很多开源工具支持 本文中不介绍这些工具的使用 第 1 章简介 1.1 Swagger 2

3 The World's Most Popular Framework for APIs. Starting January 1st 2016 the Swagger Specification has been donated( 捐赠 ) to the Open API Initiative (OAI) and is the foundation of the OpenAPI Specification. Swagger( 丝袜哥 ) 给人第一印象就是 最 (hen) 流 (niu) 行 (bai), 不懂 Swagger 咱就 out 了 它的官方网站是 Swagger 是一个简单但功能强大的 API 表达工具 它具有地球上最大的 API 工具生态系统, 数以千计的开发人员, 使用几乎所有的现代编程语言, 都在支持和使用 Swagger 使用 Swagger 生成 API, 我们可以得到交互式文档, 自动生成代码的 SDK 以及 API 的发现特性等 现在,Swagger 已经帮助包括 Apigee, Getty 图像, Intuit, LivingSocial, McKesson, 微软, Morningstar 和 PayPal 等世界知名企业建立起了一套基于 RESTful API 的完美服务系统 2.0 版本已经发布,Swagger 变得更加强大 值得感激的是,Swagger 的源码 100% 开源在 github 1.2 OpenAPI 规范 OpenAPI 规范是 Linux 基金会的一个项目, 试图通过定义一种用来描述 API 格式或 API 定义的语言, 来规范 RESTful 服务开发过程 OpenAPI 规范帮助我们描述一个 API 的基本信息, 比如 : 有关该 API 的一般性描述可用路径 (/ 资源 ) 在每个路径上的可用操作 ( 获取 / 提交...) 每个操作的输入 / 输出格式目前 V2.0 版本的 OpenAPI 规范 ( 也就是 SwaggerV2.0 规范 ) 已经发布并开源在 github 上 该文档写的非常好, 结构清晰, 方便随时查阅 关于规范的学习和理解, 本文最后还有个彩蛋 1.3 为啥要使用 OpenAPI 规范? OpenAPI 规范这类 API 定义语言能够帮助你更简单 快速的表述 API, 尤其是在 3

4 API 的设计阶段作用特别突出根据 OpenAPI 规范编写的二进制文本文件, 能够像代码一样用任何 VCS 工具管理起来一旦编写完成,API 文档可以作为 : 需求和系统特性描述的根据前后台查询 讨论 自测的基础部分或者全部代码自动生成的根据其他重要的作用, 比如开放平台开发者的手册 如何编写 API 文档? 语言 :JSON vs YAML 我们可以选择使用 JSON 或者 YAML 的语言格式来编写 API 文档 但是个人建议使用 YAML 来写, 原因是它更简单 一图胜千言, 先看用 JSON 写的文档 : { "swagger": "2.0", "info": { "version": "1.0.0", "title": "Simple API", "description": "A simple API to learn how to write OpenA PI Specification" }, "schemes": [ "https" ], "host": "simple.api", "basepath": "/openapi101", "paths": { "/persons": { "get": { "summary": "Gets some persons", "description": "Returns a list containing all pe rsons.", "responses": { "200": { "description": "A list of Person", 4

5 } } } } } } "schema": { "type": "array", "items": { "properties": { "firstname": { "type": "string" }, "lastname": { "type": "string" }, "username": { "type": "string" } } } } 再来看看同一份 API 文档的 YAML 实现 : 5

6 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. 200: description: A list of Person type: array items: required: - username properties: firstname: lastname: username: 对于普通人来说, 似乎用 YAML 更能够简化书写和阅读 这里我们并没有非此即彼的选择问题, 因为 : 几乎所用支持 OpenAPI 规范的工具都支持 YAML 有很多的工具可以实现 YAML-JSON 之间的转换 6

7 所以, 用自己喜欢的方式书写即可 ( 后面的示例文档也都是用 YAML 来写的 强烈推荐使用 YAML ) 编辑器 编写 API 文档, 其实我们只是在写一个简单的文本文件 我们可以用任何最普通的文档编辑器来写 但是为了提高效率, 还是建议使用专业的编辑工具 众多工具中, 最好的选择是 Swagger Editor, 它能够提供语法高亮 自动完成 即时预览等功能, 非常强大 左边编辑 API 文档, 右边实时预览 下面这张动图展示编辑提升功能 : 7

8 我们可以使用在线版本来编辑, 也可以非常简单的本地部署, 更多细节请参考另一 篇文档 Swagger 环境搭建.md 以及 Swagger Editor 开源仓库上的说明 第 2 章从零开始 这一章主要介绍 API 的基本组成部分, 包括提供给 API 消费者 ( 所有可能访问 API 的 个体, 下简称 消费者 ) 的的不同 HTTP 请求方法 路径, 请求和消息体中的参数, 以及返回给消费者的不同 HTTP 状态及响应消息体 2.1 最简单的例子 我们从一个最简单 ( 几乎没有东西 ) 的 API 文档开始 : 8

9 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: {} 这个文档的内容分成四部分, 下面分别来说明 OpenAPI 规范的版本号 首先我们要通过一个 swagger 属性来声明 OpenAPI 规范的版本 swagger: "2.0" 你没看错, 是 swagger, 上面已经介绍了,OpenAPI 规范是基于 Swagger 的, 在 未来的版本中, 这个属性可能会换成别的 目前这个属性的值, 暂时只能填写 为 API 描述信息 然后我们需要说明一下 API 文档的相关信息, 比如 API 文档版本 ( 注意不同于上面的 规范版本 ) API 文档名称已经可选的描述信息 info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication 9

10 2.1.3 API 的 URL 作为 web API, 一个很重要的信息就是用来给消费者使用的根 URL, 可以用协议 (http 或者 https) 主机名 根路径来描述 : schemes: - https host: simple.api basepath: /openapi101 这这个例子中, 消费者把 作为根节点来访问各种 API 因为和具体环境有关, 不涉及 API 描述的根本内容, 所以这部分信息是可选 的 API 的操作 (operation) 这个例子中, 我们没有写 API 的操作, 用一个 YAML 的空对象 {} 先占个位置 2.2 定义一个 API 操作 如果我们要展示一组用户信息, 可以这样描述 : 10

11 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. 200: description: A list of Person type: array items: required: - username properties: firstname: lastname: username: 添加一个路径 (path) 我们添加一个 /persons 的路径, 用来访问一组用户信息 : 11

12 paths: /persons: 在路径中添加一个 HTTP 方法 在每个路径中, 我们可以添加任意的 HTTP 动词来操作所需要的资源 比如需要展示一组用户信息, 我们可以在 /persons 路径中添加 get 方法, 同时还可以填写一些简单的描述信息 (summary) 或者说明该方法的一段长篇大论 (description) get: summary: Gets some persons description: Returns a list containing all persons. 这样一来, 我们调 get 方法就能获取一个用户 信息列表了 定义响应 (response) 类型 对于每个方法 ( 或操作 ), 我们都可以在响应 (responses) 中添加任意的 HTTP 状态码 ( 比如 200 OK 或者 404 Not Found 等 ) 这个例子中我们添加上 200 的响应 : 200: description: A list of Person 定义响应内容 get /persons 这个接口返回一组用户信息, 我们通过响应消息中的模式 (schema) 属性来描述清楚具体的返回内容 一组用户信息就是一个用户信息对象的数组 (array), 每一个数组元素则是一个用户信息对象 (object), 该对象包含三个 string 类型的属性 : 姓氏 名字 用户名, 其中用户名必须提供 (required) 12

13 type: array items: required: - username properties: firstname: lastname: username: 2.3 定义请求参数 (query parameters) 用户太多, 我们不想一股脑全部输出出来 这个时候, 分页输出是个不错的选择, 我们可以通过添加请求参数来实现 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. 13

14 - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer # END #### 200: description: A list of Person type: array items: required: - username properties: firstname: lastname: username: 在 get 方法中增加请求参数 首先我们在 get 方法中增加一个参数属性 : 14

15 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. # END #### 添加分页参数 在参数列表中, 我们添加两个名字 (name) 分别叫 做 pagesize 和 pagenumber 的整型 (integer) 参数, 并作简单描述 : - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer # END #### ## 这样一来, 消费者就可以通过 get /persons?pagesize=20&pagenumber=2 来访问 第 2 页的用户信息 ( 不超过 20 条 ) 了 2.4 定义路径参数 (path parameter) 15

16 有时候我们想要根据用户名来查找用户信息, 这时我们需要增加一个接口操作, 比 如可以添加一个类似 /persons/{username} 的操作来获取用户信息 注 意,{username} 是在请求路径中的参数 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person type: array items: required: - username 16

17 properties: firstname: lastname: username: /persons/{username}: get: summary: Gets a person description: Returns a single person for its username - name: username in: path required: true description: The person's username 200: description: A Person required: - username properties: firstname: lastname: username: 404: description: The Person does not exists. # END #### 添加一个 get /persons/{username} 操作 17

18 首先我们在 /persons 路径后面, 增加一个 /persons/{username} 的路径, 并定义一 个 get ( 操作 ) 方法 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: username: /persons/{username}: get: summary: Gets a person description: Returns a single person for its username # END #### 定义路径参数 username 因为 {username} 是路径参数, 我们需要先像请求参数一样将它添加到 parameters 属性中, 注意名称应该同上面大括号 ( { } ) 里面的名称一致 并通过 in 这个属性, 来表示它是一个路径 (path) 参数 18

19 - name: username in: path required: true description: The person's username 定义路径参数时很容易出现的问题就是忘记 : required: true,swagger 的自动完成功能中没有包含这个属性定义 如果没有写 require 属性, 默认值是 false, 也就是说 username 参数时可选的 可事实上, 作为路径参数, 它是必需的 定义响应消息 别忘了获取单个用户信息也需要填写 200 响应消息, 响应消息体的内容就是之前描 述过的用户信息 ( 用户信息列表中的一个元素 ): 200: description: A Person required: - username properties: firstname: lastname: username: 当然,API 的提供者会对 username 进行校验, 如果查无此人, 应该返回 404 的异 常状态 所以我们再加上 404 状态的响应 : 404: description: The Person does not exists. 19

20 2.5 定义消息体参数 (body parameter) 当我们需要添加一个用户信息时, 我们需要一个能够提供 post /persons 的 API 操 作 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person type: array items: required: 20

21 - username properties: firstname: lastname: username: post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. required: - username properties: firstname: lastname: username: 204: description: Persons succesfully created. 400: description: Persons couldn't have been created. # END #### /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username 21

22 in: path required: true description: The person's username 200: description: A Person required: - username properties: firstname: lastname: username: 404: description: The Person does not exists 添加一个 post /persons 操作 首先在 /persons 路径下廷加一个 post 操作 : paths: /persons: post: summary: Creates a person description: Adds a new person to the persons list 定义消息体参数 接下来我们给 post 方法添加参数, 通过 in 属性显式说明参数是在 body 中的 参数的定义参考 get /persons/{username} 的 200 响应消息体参数, 也就是包含用户的姓氏 名字 用户名 22

23 - name: person in: body description: The person to create. required: - username properties: firstname: lastname: username: 定义响应消息 最后不要忘记定义 post 操作的响应消息 204: description: Persons succesfully created. 400: description: Persons couldn't have been created. 第 3 章文档瘦身 现在我们已经学会了编写 API 文档的基本方法 不过上面的例子中存在一些重复, 这对于程序员的嗅觉来说, 就是代码的 坏味道 这一章我们一起学习如何通过抽取可重用的定义 (definitions) 来简化 API 文档 3.1 简化数据模型 我们认真观察第 2 章最后输出的 API 文档, 很容易发现 Person 的定义出现了三次, 非常的不 DRY 23

24 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person type: array items: #START 第 1 次定义 ############# required: - username properties: 24

25 firstname: lastname: username: # END 第 1 次定义 ############# post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. #START 第 2 次定义 ############# required: - username properties: firstname: lastname: username: # END 第 2 次定义 ############# 204: description: Persons succesfully created. 400: description: Persons couldn't have been created. /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username 25

26 in: path required: true description: The person's username 200: description: A Person #START 第 3 次定义 ############# required: - username properties: firstname: lastname: username: # END 第 3 次定义 ############# 404: description: The Person does not exists. 现在, 我们通过可重用的定义 (definition) 来重构这个文档 : swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 26

27 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person $ref: "#/definitions/persons" # END #### post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. $ref: "#/definitions/person" # END #### 204: description: Persons succesfully created. 27

28 400: description: Persons couldn't have been created. /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username in: path required: true description: The person's username 200: description: A Person $ref: "#/definitions/person" # END #### 404: description: The Person does not exists. #START 新增定义 ############## definitions: Person: required: - username properties: firstname: lastname: username: Persons: type: array items: 28

29 $ref: "#/definitions/person" # END 新增定义 ############### ################# 文档简化了很多 这得益于 OpenAPI 规范中关于定义 (definition) 的章节中允许我 们 一处定义, 处处使用 添加定义 (definitions) 项 我们首先在 API 文档的尾部添加一个定义 (definitions) 项 ( 其实它也可以放在文 档的任意位置, 只不过大家习惯放在文档末尾 ): 404: description: The Person does not exists. definitions: # END #### 增加一个可重用的 ( 对象 ) 定义 然后我们增加一个 Person 对象的定义 : 29

30 definitions: Person: required: - username properties: firstname: lastname: username: # END #### 引用一个定义来增加另一个定义 在定义项中, 我们可以立即引用刚才定义好的 Person 来增加另一个定义,Persons Persons 是一个 Person 对象的数组 与之前直接定义的不同之处是, 我们增加了一个引用 (reference) 属性, 也就是 $ref 来引用 Person Persons: type: array items: $ref: "#/definitions/person" 在响应消息中使用定义 一旦定义好了 Person, 我们可以把原来在响应消息中相应的定义字段替换掉 get/persons 原来 : 30

31 200: description: A list of Person type: array items: required: - username properties: firstname: lastname: 现在 : 200: description: A list of Person $ref: "#/definitions/persons" get/persons/{username} 原来 : 31

32 200: description: A Person required: - username properties: firstname: lastname: username: 现在 : 200: description: A Person $ref: "#/definitions/person" 在参数中使用定义 不仅仅在消息中可以使用定义, 在参数中也可以使用 post /persons 原来 : 32

33 post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. required: - username properties: firstname: lastname: username: 现在 : post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. $ref: "#/definitions/person" 3.2 简化响应消息 我们看到了引用 ($ref) 的作用, 接下来我们再把它用到响应消息的定义中 : swagger: "2.0" info: 33

34 version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person $ref: "#/definitions/persons" 500: $ref: "#/responses/standard500errorresponse" # END #### post: summary: Creates a person description: Adds a new person to the persons list. 34

35 - name: person in: body description: The person to create. $ref: "#/definitions/person" 204: description: Persons succesfully created. 400: description: Persons couldn't have been created. 500: $ref: "#/responses/standard500errorresponse" # END #### /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username in: path required: true description: The person's username 200: description: A Person $ref: "#/definitions/person" 404: description: The Person does not exists. 500: $ref: "#/responses/standard500errorresponse" # END #### 35

36 definitions: Person: required: - username properties: firstname: lastname: username: Persons: type: array items: $ref: "#/definitions/person" Error: properties: code: message: Standard500ErrorResponse: description: An unexpected error occured. $ref: "#/definitions/error" # END #### 定义可重用的 HTTP 500 响应 发生 HTTP 500 错误时, 假如我们希望每一个 API 操作都返回一个带有错误码 (error code) 和描述信息 (message) 的响应, 我们可以这样做 : paths: 36

37 /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person $ref: "#/definitions/persons" 500: description: An unexpected error occured. properties: code: message: # END #### post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. $ref: "#/definitions/person" 37

38 204: description: Persons succesfully created. 400: description: Persons couldn't have been created. 500: description: An unexpected error occured. properties: code: message: # END #### /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username in: path required: true description: The person's username 200: description: A Person $ref: "#/definitions/person" 404: description: The Person does not exists. 500: description: An unexpected error occured. 38

39 properties: code: message: # END #### 增加一个 Error 定义 按照 一处定义 处处引用 的原则, 我们可以在定义项中增加 Error 的定义 : definitions: Person: required: - username properties: firstname: lastname: username: Persons: type: array items: $ref: "#/definitions/person" Error: properties: code: message: # END #### 而且我们也学会了使用引用 ($ref), 所以我们可以这样写 : 39

40 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A list of Person $ref: "#/definitions/persons" 500: description: An unexpected error occured. $ref: "#/definitions/error" # END #### post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. $ref: "#/definitions/person" 204: 40

41 description: Persons succesfully created. 400: description: Persons couldn't have been created. 500: description: An unexpected error occured. $ref: "#/definitions/error" # END #### /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username in: path required: true description: The person's username 200: description: A Person $ref: "#/definitions/person" 404: description: The Person does not exists. 500: description: An unexpected error occured. $ref: "#/definitions/error" # END #### 定义一个可重用的响应消息 41

42 上面的文档中, 还是有一些重复的内容 我们可以根据 OpenAPI 规范中的 responses 章节的描述, 通过定义一个可重用的响应消息, 来进一步简化文档 definitions: Person: required: - username properties: firstname: lastname: username: Persons: type: array items: $ref: "#/definitions/person" Error: properties: code: message: Standard500ErrorResponse: description: An unexpected error occured. $ref: "#/definitions/error" # END #### 注意 : 响应消息中引用了 Error 的定义 使用已定义的响应消息 我们还是通过引用 ($ref) 来使用一个已经定义好的响应消息, 比如 : 42

43 get /users 200: description: A list of Person $ref: "#/definitions/persons" 500: $ref: "#/responses/standard500errorresponse" # END #### post/users 204: description: Persons succesfully created. 400: description: Persons couldn't have been created. 500: $ref: "#/responses/standard500errorresponse" # END #### get/users/{username} 43

44 200: description: A Person $ref: "#/definitions/person" 404: description: The Person does not exists. 500: $ref: "#/responses/standard500errorresponse" # END #### 3.3 简化参数定义 类似数据模型 响应消息的简化, 参数定义的简化也很容易 swagger: "2.0" info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specif ication schemes: - https host: simple.api basepath: /openapi101 paths: /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. 44

45 - $ref: "#/parameters/pagesize" - $ref: "#/parameters/pagenumber" # END #### 200: description: A list of Person $ref: "#/definitions/persons" 500: $ref: "#/responses/standard500errorresponse" post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body description: The person to create. $ref: "#/definitions/person" 204: description: Person succesfully created. 400: description: Person couldn't have been created. 500: $ref: "#/responses/standard500errorresponse" /persons/{username}: - $ref: "#/parameters/username" # END #### get: summary: Gets a person description: Returns a single person for its username. 45

46 200: description: A Person $ref: "#/definitions/person" 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" delete: summary: Deletes a person description: Delete a single person identified via its use rname 204: description: Person successfully deleted. 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" /persons/{username}/friends: - $ref: "#/parameters/username" # END #### get: summary: Gets a person's friends description: Returns a list containing all persons. The li st supports paging. - $ref: "#/parameters/pagesize" - $ref: "#/parameters/pagenumber" # END #### 46

47 200: description: A person's friends list $ref: "#/definitions/persons" 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" definitions: Person: required: - username properties: firstname: lastname: username: Persons: type: array items: $ref: "#/definitions/person" Error: required: - code - message properties: code: message: Standard500ErrorResponse: description: An unexpected error occured. $ref: "#/definitions/error" PersonDoesNotExistResponse: 47

48 description: Person does not exist. username: name: username in: path required: true description: The person's username pagesize: name: pagesize in: query description: Number of persons returned type: integer pagenumber: name: pagenumber in: query description: Page number type: integer # END #### 路径参数只定义一次 如果我们现在想要删除一个用户的信息, 就需要增加一个 delete /persons/{username} 的操作, 可以这样 : /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username in: path required: true 48

49 description: The person's username # END #### 200: description: A Person $ref: "#/definitions/person" 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" delete: summary: Deletes a person description: Delete a single person identified via its use rname - name: username in: path required: true description: The person's username # END #### 204: description: Person successfully deleted. 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" 但是上面两次对参数 username 的定义, 却让人有点难受 好消息是我们可以定 义路径级别的参数 ( 之前都是定义在操作级别 ) 49

50 /persons/{username}: - name: username in: path required: true description: The person's username # END #### get: summary: Gets a person description: Returns a single person for its username. 200: description: A Person $ref: "#/definitions/person" 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" delete: summary: Deletes a person description: Delete a single person identified via its use rname 204: description: Person successfully deleted. 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" 定义可重用的参数 50

51 如果我们想根据用户名查找该用户的朋友圈, 可以添加一个 get /persons/{username}/friends 的操作 根据前面所学的内容, 第一反应应该这样 写 : /persons/{username}/friends: - name: username in: path required: true description: The person's username get: summary: Gets a person's friends description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer 200: description: A person's friends list $ref: "#/definitions/persons" 404: $ref: "#/responses/persondoesnotexistresponse" 500: $ref: "#/responses/standard500errorresponse" 可以看到, 关于 username pagesize pagenumber 的定义跟前面的 /person/{username} get /persons 中的定义重复 如何消除重复呢? 定义可重用的参数 51

52 根据 3.1 和 3.2 中的内容, 我们可以参考 OpenAPI 规范, 融汇贯通 username: name: username in: path required: true description: The person's username pagesize: name: pagesize in: query description: Number of persons returned type: integer pagenumber: name: pagenumber in: query description: Page number type: integer 使用定义参数 借助万能的引用 ($ref), 这都是小菜一碟 比如 : get /persons 原来 : 52

53 /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer # END #### 现在 : /persons: get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. - $ref: "#/parameters/pagesize" - $ref: "#/parameters/pagenumber" # END #### get 和 delete /persons/{username} 原来 : 53

54 /persons/{username}: - name: username in: path required: true description: The person's username # END #### 现在 : /persons/{username}: - $ref: "#/parameters/username" # END #### get /persons/{username}/friends 原来 : 54

55 /persons/{username}/friends: - name: username in: path required: true description: The person's username # END #### get: summary: Gets a person's friends description: Returns a list containing all persons. The li st supports paging. - name: pagesize in: query description: Number of persons returned type: integer - name: pagenumber in: query description: Page number type: integer # END #### 现在 : 55

56 /persons/{username}/friends: - $ref: "#/parameters/username" # END #### get: summary: Gets a person's friends description: Returns a list containing all persons. The li st supports paging. - $ref: "#/parameters/pagesize" - $ref: "#/parameters/pagenumber" # END #### 第 4 章深入了解一下 通过前面的练习, 我们可以写出一篇结构清晰 内容精炼的 API 文档了 可是 OpenAPI 规范还给我们提供了更多的便利和惊喜, 等着我们去了解和掌握 这一章主要介绍用于定义属性和数据模型的高级方法 4.1 私人定制 Primitive data types in the Swagger Specification are based on the types supported by the JSON-Schema Draft 4. Models are described using the Schema Object which is a subset of JSON Schema Draft 4. OpenAPI Specification Data Types 使用 JSON Schema Draft 4, 我们可以定义任意类型的各种属性, 举例说明 字符串 (Strings) 长度和格式 56

57 当定义个字符串属性时, 我们可以定制它的长度及格式 : 属性 类型 描述 minlength number 字符串最小长度 maxlength number 字符串最大长度 pattern string 正则表达式 ( 如果你暂时还不熟悉正则表达式, 可以看看 Regex 101) 如果我们规定用户名是长度介于 8~64, 而且只能由小写字母和数字来构成, 那么我 们可以这样写 : username: pattern: "[a-z0-9]{8,64}" minlength: 8 maxlength: 日期和时间 日期和时间的处理参考 RFC 3339, 我们唯一要做的就是写对格式 : 格式 属性包含内容 属性示例 date ISO8601 full-date datetime ISO8601 date-time T16:06:05Z 如果我们在 Person 的定义中增加生日和上次登录时间时间戳, 我们可以这样 写 : dateofbirth: format: date lasttimeonline: format: datetime 如果想深入掌握 API 中处理日期和时间的方法, 我们应该继续阅读 Jason Harmon 写的文章 5 laws of API dates and times 57

58 4.1.3 数字类型和范围 当我们定义一个数字类型的属性时, 我们可以规定它是一个整型 长型 浮点型或 者双浮点型 名称 类型 格式 integer integer int32 long integer int64 float number float double number double 和字符串一样, 我们也可以定义数字属性的范围, 比如 : 属性 类型 描述 minimum number 最小值 maximum number 最大值 exclusiveminimum boolean 数值必须 > 最小值 exclusivemaximum boolean 数值必须 < 最大值 multipleof number 数值必须是 multipleof 的整数倍 如果我们规定 pagesize 必须是整数, 必须 > 0 且 <=100, 还必须是 10 的整数 倍, 可以这样写 : pagesize: name: pagesize in: query description: Number of persons returned type: integer format: int32 minimum: 0 exclusiveminimum: true maximum: 100 exclusivemaximum: false multipleof: 枚举类型 58

59 我们还可以定义枚举类型, 比如定义 Error 时, 我们可以这样写 : code: enum: - DBERR - NTERR - UNERR code 的值只能从三个枚举值中选择 数值的大小和唯一性 数字的大小和唯一性通过下面这些属性来定义 : 属性 类型 描述 minitems number 数值中的最小元素个数 maxitem number 数值中的最大元素个数 uniqueitems boolean 标示数组中的元素是否唯一 比如我们定义一个用户数组 Persons, 希望返回的用户信息条数介于 10~100 之间, 而且不能有重复的用户信息, 我们可以这样写 : Persons: properties: items: type: array minitems: 10 maxitems: 100 uniqueitems: true items: $ref: "#/definitions/person" 二进制数据 可以用 string 类型来表示二进制数据 : 59

60 格式 属性包含 byte binary Base64 编码字符 任意十进制的数据序列 比如我们需要在用户信息中增加一个头像属性 (avatarbase64png) 用 base64 编 码的 PNG 图片来表示, 可以这样写 : avatarbase64png: format: byte 4.2 高级数据定义 读写操作同一定义的数据 有时候我们读取资源信息的内容会比我们写入资源信息的内容 ( 属性 ) 更多, 这很常见 是不是意味着我们必须专门为读取资源和写入资源分别定义不同的数据模型呢? 幸运的是,OpenAPI 规范中提供了 readonly 字段来帮我们解决整问题 比如 : lasttimeonline: format: datetime readonly: true 上面这个例子中, 上次在线时间 (lasttimeonline ) 是 Person 的一个属性, 我们 获取用户信息时需要这个属性 但是很明显, 在创建用户时, 我们不能把这个属性 post 到服务器 于是我们可以把它标记为 readonly 组合定义确保一致性 一致性设计是在编写 API 文档时需要重点考虑的问题 比如我们在获取一组用户信息时, 需要同时获取页面信息 ( totalitems, totalpage, pagesize, currentpage) 等, 而且这些信息必须在根节点上 60

61 怎么办呢? 首先想到的做法就是 : PagedPersonsV1: properties: items: type: array items: $ref: "#/definitions/person" totalitems: type: integer totalpages: type: integer pagesize: type: integer currentpage: type: integer 如果其他 API 操作也需要这些页面信息, 那就意味着这些属性必须一遍又一遍的定义 不仅重复体力劳动, 而且还很危险 : 比如忘记了其中的一两个属性, 或者需要添加一个新的属性进来, 那就是霰弹式的修改, 想想都很悲壮 稍微好一点的做法, 就是根据前面学习的内容, 把这几个属性抽取出来, 建立一个 Paging 模型, 一处定义 处处使用 : 61

62 PagedPersonsV2: properties: items: type: array items: $ref: "#/definitions/person" paging: $ref: "#/definitions/paging" Paging: properties: totalitems: type: integer totalpages: type: integer pagesize: type: integer currentpage: type: integer 但是, 页面属性都不再位于根节点! 与我们前面设定的要求不一样了 怎么破? JSON Schema v4 property 中定义的 allof, 能帮我们解围 : PagedPersons: allof: - $ref: "#/definitions/persons" - $ref: "#/definitions/paging" 上面这个例子表示,PagedPersons 根节点下, 具有将 Persons 和 Paging 展开后 的全部属性 allof 同样可以使用行内的数据定义, 比如 : 62

63 PagedCollectingItems: allof: - properties: items: type: array minitems: 10 maxitems: 100 uniqueitems: true items: $ref: "#/definitions/collectingitem" - $ref: "#/definitions/paging" 数据模型的继承 (TODO) 目前各工具支持程度不高, 待续 第 5 章输入输出模型 这一章主要介绍如何定义高度精确化的参数和响应消息等 5.1 高级参数定义 必带参数和可选参数 我们已经知道使用关键字 required 来定义一个必带参数 定义必带参数和可选参数 在一个参数中, required 是一个 boolean 型的可选值 它的默认值是 false 比如在某个操作中,username 是必填参数 : 63

64 username: name: username in: path required: true # END #### description: The person's username 定义必带属性和可选属性根据定义, required 是一个字符串列表, 列表中包含各必带参数名 如果某个参数在这张列表中找不到, 那就说明它不是必带参数 如果没有定义 required, 就说明所有参数都是可选 如果 required 定义在一个 HTTP 请求上, 这说明所有的请求参数都是必填 在 POST persons 中有 Person 的定义, 在这里 username 这个属性是必带的, 我们可以指定它为 required, 其他非必带字段则不指定 : 64

65 Person: required: - username # END #### properties: firstname: lastname: username: pattern: '[a-z0-9]{8,64}' minlength: 8 maxlength: 64 dateofbirth: format: date lasttimeonline: format: date-time readonly: true avatarbase64png: format: byte default: data:image/png;base64,i spokenlanguages: $ref: '#/definitions/spokenlanguages' 带默认值的参数 通过关键字 default, 我们可以定义一个参数的默认值 当这个参数不可得 ( 请求未带或者服务器未返回 ) 时, 这个参数就取默认值 因此设定了某个参数的默认值后, 它是否 required 就没意义了 定义参数的默认值 65

66 我们定义参数 pagesize 的默认值为 20, 那么如果请求时没有填写 pagesize, 服 务器也会默认返回 20 个元素 pagesize: name: pagesize in: query description: Number of persons returned type: integer format: int32 minimum: 0 exclusiveminimum: true maximum: 100 exclusivemaximum: false multipleof: 10 default: 20 # END #### 定义属性的默认值 我们在定义 Person 对象时, 希望给每个用户一个默认头像, 也就是要给 avatarbase64png 属性一个默认值 默认头像 : 66

67 Person: required: - username properties: firstname: lastname: username: pattern: '[a-z0-9]{8,64}' minlength: 8 maxlength: 64 dateofbirth: format: date lasttimeonline: format: date-time readonly: true avatarbase64png: format: byte default: data:image/png;base64,ivborw0kggoaaaansuheuga rkjggg== # END #### spokenlanguages: $ref: '#/definitions/spokenlanguages' 带空值的参数 在 GET /persons 时, 如果我们想添加一个参数来过滤 是否通过实名认证 的用户, 应该怎么做呢? 首先想到的是这样 :GET /persons? page=2&includeverifiedusers=true, 问题是 includeverifiedusers 语义已经如此 67

68 清晰, 而让 =true 显得很多余 我们能不能直接用 :GET /persons? page=2&includeverifiedusers 呢? 要做到这种写法, 我们需要一个关键字 allowemptyvalue 我们定义 includeverifiedusers 时允许它为空 那么如果我们请求 GET /persons? page=2&includeverifiedusers 则表示需要过滤 实名认证 用户, 如果我们直接请求 GET /persons?page=2 则表示不过滤 : includenonverifiedusers: name: includenonverifiedusers in: query type: boolean default: false allowemptyvalue: true # END #### 参数组 设计 API 的时候, 我们经常会遇到在 GET 请求中需要携带一组请求参数的情况 如何在 API 文档章呈现呢? 很简单, 我们只需要设定参数类型 (type) 为 array, 并选择合适的组合格式 (collectionformat) 就行了 COLLECTIONFORMAT csv (default value) ssv tsv 描述 Comma separated values( 逗号分隔 ) foo,bar Space separated values( 空格分隔 ) foo bar Tab separated values( 反斜杠分隔 ) foo\tbar pipes Pipes separated values( 竖线分隔 ) `foo\ bar` multi 单属性可以取多个值, 比如 foo=bar&foo=baz. 只适用于查询参数和表单参数 68

69 比如我们想根据多种参数 (username, firstname, lastname, lasttimeonline ) 等来对 Person 进行带排序的查询 我们需要一个这样的 API 请求 : GET /persons?sort=-lasttimeonline +firtname +lastname 用于排序的参数是 sort, + 表示升序, - 表示降序 相应的 API 文档, 可以这样写 : sortpersons: name: sort in: query type: array uniqueitems: true minitems: 1 maxitems: 3 collectionformat: pipes items: pattern: '[-+](username lasttimeonline firstname lastname)' 现在我们就能搞定 GET /persons?sort=-lasttimeonline +firtname +lastname 这种 请求了 当然, 我们还可以指定排序的默认值, 锦上添花 69

70 sortpersons: name: sort in: query type: array uniqueitems: true minitems: 1 maxitems: 3 collectionformat: pipes items: pattern: '[-+](username lasttimeonline firstname lastname)' default: - -lasttimeonline - +username # END #### 消息头 (Header) 参数 参数, 按照位置来分, 不仅仅包含路径参数 请求参数和消息体参数, 还包括消息头参数和表单参数等 比如我们可以在 HTTP 请求的消息头上加一个 User-Agent ( 用于跟踪 调试或者其他 ), 可以这样定义它 : useragent: name: User-Agent in: header required: true 然后像使用其他参数一样使用它 : 70

71 paths: /persons: - $ref: '#/parameters/useragent' 表单参数 有些 js-less-browser 的老浏览器不支持 POST JSON 数据, 比如在创建用户时, 只 能够以这样个格式请求 : POST /js-less-persons username=apihandyman&firstname=api&lastname=handyman 没有问题, 丝袜哥可以搞定 我们只需要把各个属性的 in 关键字定义 为 formdata, 然后设置 consumes 的媒体类型为 application/x-www-formurlencoded 即可 post: summary: Creates a person description: For JS-less partners consumes: - application/x-www-form-urlencoded # END #### produces: - text/html - name: username in: formdata # END #### required: true pattern: '[a-z0-9]{8,64}' 71

72 minlength: 8 maxlength: 64 - name: firstname in: formdata # END #### - name: lastname in: formdata - name: dateofbirth in: formdata # END #### format: date '204': description: Person succesfully created 文件参数 当我们要处理一个请求, 输入类型是文件时, 我们需要 : 使用 multipart/form-data 媒体类型 ; 设置参数的 in 关键字为 formdata; 设置参数的类型 (type) 为 file 比如 : 72

73 /images: - $ref: '#/parameters/useragent' post: summary: Uploads an image consumes: - multipart/form-data - name: image in: formdata type: file '200': description: Image's ID properties: imageid: 有时候我们想限定输入文件的类型 ( 后缀 ), 很不幸的是, 根据现在 V2.0 的规范暂时还做不到 The spec doesn t allow specifying a content type for specific form data parameters. It s a limitation of the spec. Ron Ratovsky comment in Swagger UI 609 issue 参数的媒体类型 一个 API 可以消费各种不同的媒体类型, 比如说最常见的是 application/json 类型的数据, 当然这不是 API 唯一支持的类型 我们可以在文档的根节点或者一个操作的根节点下添加关键字 consumes, 来定义这个操作能够消费的媒体类型 比如我们的 API 全部都接受 JSON 和 YAML 的数据, 那我们可以在文档的根节点下添加 : consumes: - application/json - application/x-yaml 73

74 如果某个操作 ( 比如上传图片的操作 ) 很特殊, 它可以通过自己添加 consumes 来覆盖全局设置 : /images: - $ref: '#/parameters/useragent' post: summary: Uploads an image consumes: - multipart/form-data # END #### - name: image in: formdata type: file '200': description: Image's ID properties: imageid: 5.2 高级响应消息定义 不带消息体的响应消息 不带消息体的响应很常见, 比如 HTTP 204 状态响应本身就表示服务器返回不带任何消息内容的成功消息 要定义一个不带消息体的响应很简单, 我们只需要写响应状态和描述就行了 : 74

75 post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body required: true description: The person to create. $ref: '#/definitions/person' '204': description: Person succesfully created. # END #### 响应消息中的必带参数和可选参数 与请求消息中类似, 我们使用 required 参数来表示, 比如请求一个用户信息时, 服务器必须返回 username, 可以这样写 : 75

76 Person: required: - username # END #### properties: firstname: lastname: username: pattern: '[a-z0-9]{8,64}' minlength: 8 maxlength: 64 dateofbirth: format: date lasttimeonline: format: date-time readonly: true 响应消息头 API 的返回结果不仅仅体现下 HTTP 状态和响应消息体, 还可以在响应消息头上做文章 比如我们可以限定一个 API 的使用次数和使用时间段, 在响应消息头中, 增加一个属性 X-Rate-Limit-Remaining 来表示 API 可调用的剩余次数, 增加另一个属性 X-Rate-Limit-Reset 来表示 API 的有效截止时间 76

77 post: summary: Creates a person description: Adds a new person to the persons list. - name: person in: body required: true description: The person to create. $ref: '#/definitions/person' '204': description: Person succesfully created. headers: X-Rate-Limit-Remaining: type: integer X-Rate-Limit-Reset: format: date-time # END #### 美中不足的是, 对于这种响应消息头的修改, 目前 2.0 规范暂时还不支持 一次定 义 处处使用 默认响应消息 我们在定义响应消息时, 通常会列举不同的 HTTP 状态结果 如果有些状态不在我们 API 文档的定义范围 ( 比如服务器需要返回 993 的状态 ), 该怎么处理呢? 这时需要通过关键字 default 来定义一个默认响应消息, 用于各种定义之外的状态响应, 比如 : 77

78 delete: summary: Deletes a person description: Delete a single person identified via its use rname '204': description: Person successfully deleted. headers: X-Rate-Limit-Remaining: type: integer X-Rate-Limit-Reset: format: date-time '404': $ref: '#/responses/persondoesnotexistresponse' '500': $ref: '#/responses/standard500errorresponse' default: $ref: '#/responses/totallyunexpectedresponse' # END #### 目前这个配置也不支持 一次定义, 处处使用 响应消息的媒体类型 与请求消息一样, 我们也可以定义响应消息所支持的媒体类型, 不同的是我们要用到关键字 produces ( 与请求消息中的 consumes 相对, 由此可见,API 文档描述的主体是服务提供者 ) 比如, 我们可以在文档的根路径下全局设置 : produces: - application/json - application/x-yaml 78

79 也可以在某个操作的根路径下覆盖设置 : /images/{imageid}: - $ref: '#/parameters/useragent' get: summary: Gets an image - name: imageid in: path required: true produces: - image/png - image/gif - image/jpeg - application/json - application/x-yaml # END #### '200': description: The image headers: X-Rate-Limit-Remaining: type: integer X-Rate-Limit-Reset: format: date-time '404': description: Image do not exists headers: X-Rate-Limit-Remaining: type: integer X-Rate-Limit-Reset: format: date-time '500': 79

80 $ref: '#/responses/standard500errorresponse' default: $ref: '#/responses/totallyunexpectedresponse' 5.3 定义某个参数只存在于响应消息中 如前章节 中已经提到的, 定义一个对象, 其中某个属性我们只希望在响应消息中携带, 而不希望在请求消息中携带, 应该用 readonly 关键字来表示 考虑到内容的完整性, 这里再介绍一下 比如 Person 对象中的 lasttimeonline 这个属性, 注册用户时我们不需要填写, 但是在获取用户信息时, 需要提供给服务消费者 : Person: required: - username properties: firstname: lastname: username: pattern: '[a-z0-9]{8,64}' minlength: 8 maxlength: 64 dateofbirth: format: date lasttimeonline: format: date-time readonly: true # END #### 80

81 第 6 章不要让 API 裸奔 这一章主要介绍 API 文档中如何描述安全相关的内容 6.1 定义安全 安全相关内容的定义一般放在 API 文档根目录下的 securitydefinition 中, 它包括一组具体的命名安全项, 每一个命名安全定义可能包括下面三种安全类型之一 :basic,apikey,oauth 基础鉴权 (Basic Authentication) 要定义一个基础 (basic) 鉴权, 我们只需要将 type 设置为 basic 即可 : securitydefinitions: UserSecurity: type: basic AdminSecurity: type: basic MediaSecurity: type: basic 这个例子中, 我们定义了三种安全说明 (UserSecurity,AdminSecurity, MediaSecurity), 都属于基础鉴权 API 秘钥鉴权 (API Key) 要定义一个 API 秘钥鉴权, 我们需要 : 设置 type 为 apikey 通过关键字 in 指示 api 秘钥所在位置 通常 api 秘钥会放在消息头 请求参数或者消息体中给安全项命个名字 81

82 securitydefinitions: UserSecurity: type: apikey in: header name: SIMPLE-API-KEY AdminSecurity: type: apikey in: header name: ADMIN-API-KEY MediaSecurity: type: apikey in: query name: MEDIA-API-KEY 在这个例子中, 我们定义了三个 apikey 类型的安全项 : UserSecurity 定义了一个名为 SIMPLE-API-KEY 的参数在消息头 (header) AdminSecurity 定义了一个名为 ADMIN-API-KEY 的参数在消息头 (header) MediaSecurity 定义了一个名为 MEDIA-API-KEY 的参数在请求参数中 Oauth2 鉴权 流程 (Flow) 和 URL 当我们定义个 Oauth2 类型的安全项上, 我们通常会定义 Oauth2 的流程 (flow) 和并根据选定的流程配置相应的鉴权地址 (authorizationurl) 和 / 或令牌地址 (tokenurl) 流程 所需要的 URL implicit authorizationurl( 鉴权地址 ) password tokenurl( 令牌地址 ) application accesscode tokenurl authorizationurl and tokenurl 比如 : 82

83 securitydefinitions: OauthSecurity: type: oauth2 flow: accesscode authorizationurl: ' tokenurl: ' 在这个例子中, 我们定义了一个 Oauth2 的安全项, 配置的流程是 accesscode 方 式, 同时配置了鉴权地址和令牌地址 作用范围 (scope) 我们借助关键字 scopes 并通过哈希键值对来还可以配置 Oauth2 安全项的作用范 围 (scope), 键值对的键表示作用范围名称 ; 值是它的相关描述, 比如 : securitydefinitions: OauthSecurity: type: oauth2 flow: accesscode authorizationurl: ' tokenurl: ' scopes: admin: Admin scope user: User scope media: Media scope 在这个例子中, 我们给 OauthSecurity 安全项添加了三个作用范围 (admin,user,media) 6.2 使用安全定义 现在我们已经在 securitydefinition 中定义好了安全项, 现在我们可以将将它们应用 到文档中了 使用的时候, 我们通过 security 关键字, 把安全项添加进去 基础鉴权 API 级别 83

84 securitydefinitions: UserSecurity: type: basic AdminSecurity: type: basic MediaSecurity: type: basic security: - UserSecurity: [] # END #### paths: /persons: 在这个例子中, 我们在 API 文档的根路径下直接使用了安全项 UserSecurity, 它的 作用范围是整个 API 文档 操作级别 比如我们在添加或者修改用户信息时, 需要进行管理员鉴权, 可以在 POST /persons 操作中增加安全项 : post: summary: Creates a person description: Adds a new person to the persons list. security: - AdminSecurity: [] # END #### 而在上传图片时, 需要进行媒体操作鉴权, 可以在 POST /images 操作中增加安全 项 : 84

85 /images: - $ref: '#/parameters/useragent' post: summary: Uploads an image security: - MediaSecurity: [] # END #### API 秘钥鉴权 使用方式和基础鉴权一样, 可以在 API 级别和操作级别使用 : securitydefinitions: UserSecurity: type: apikey in: header name: SIMPLE-API-KEY AdminSecurity: type: apikey in: header name: ADMIN-API-KEY MediaSecurity: type: apikey in: query name: media-api-key security: - UserSecurity: [] # END #### paths: /persons: 85

86 post: summary: Creates a person description: Adds a new person to the persons list. security: - AdminSecurity: [] Oauth2 鉴权 Oauth2 鉴权的使用和上面的两种鉴权方式基本相同, 不同之处在于我们可以指定它的哪一个作用范围 (scope) 比如 API 级别的鉴权 : securitydefinitions: OauthSecurity: type: oauth2 flow: accesscode authorizationurl: ' tokenurl: ' scopes: admin: Admin scope user: User scope media: Media scope security: - OauthSecurity: - user # END #### paths: /persons: 操作级别的鉴权 : 86

87 post: summary: Creates a person description: Adds a new person to the persons list. security: - OauthSecurity: - admin 在这个例子中, 作用范围 admin 将覆盖全局配置的作用范围 user 6.3 使用多种安全配置 OpenAPI 规范并没有限定我们只能使用一种安全项 下面的例子将展示如何使用多 种安全配置 安全定义 securitydefinitions: OauthSecurity: type: oauth2 flow: accesscode authorizationurl: ' tokenurl: ' scopes: admin: Admin scope user: User scope MediaSecurity: type: apikey in: query name: media-api-key LegacySecurity: type: basic 这个例子中, 我们定义了三种鉴权方式 全局安全配置 87

88 security: - OauthSecurity: - user - LegacySecurity: [] 这个配置的意思是用户可以通过两种方式中的任意一种来访问我们提供的 API 接 口 覆盖全局配置 post: summary: Creates a person description: Adds a new person to the persons list. security: - OauthSecurity: - admin - LegacySecurity: [] 在 POST /persons 操作中,OauthSecurity 的作用范围被覆写为 admin 此时用户 可以通过 admin 的 Oauth2 或者 legacysecurity 来鉴权使用这个操作 /images: - $ref: '#/parameters/useragent' post: summary: Uploads an image security: - MediaSecurity: [] 在 POST/images 操作中, 用 MediaSecurity 整体覆写了全局安全项, 用户只能通过 MediaSecurity 鉴权使用这个操作 第 7 章让文档的可读性更好 88

89 7.1 分类标签 (Tags) 通过关键字 tags 我们可以对文档中接口进行归类, tags 的本质是一个字符串 列表 tags 定义在文档的根路径下 单标签 比如说 GET /persons 属于用户 (Person) 这个分类的, 那么我们可以给它贴个标 签 : paths: /persons: - $ref: '#/parameters/useragent' get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. operationid: searchusers tags: - Persons # END #### 多标签 一个操作也可以同时贴几个标签, 比如 : 89

90 /js-less-consumer-persons: - $ref: '#/parameters/useragent' post: summary: Creates a person description: For JS-less partners operationid: createuserjs deprecated: true tags: - JSLess - Persons 贴上标签后, 在 Swagger Editor 和 Swagger UI 中能够自动归类, 我们可以按照标签 来筛选接口, 试试吧? 7.2 无处不在的描述文字 (Descriptions) description 这个属性几乎是无处不在, 为了提高文档的可读性, 我们应该在必 要的地方都加上描述文字 安全项的描述 90

91 securitydefinitions: OauthSecurity: description: New Oauth security system. Do not use MediaSecu rity or LegacySecurity. type: oauth2 flow: accesscode authorizationurl: ' tokenurl: ' scopes: admin: Admin scope user: User scope MediaSecurity: description: Specific media security for backward compatibil ity. Use OauthSecurity instead. type: apikey in: query name: media-api-key LegacySecurity: description: Legacy security system for backward compatibili ty. Use OauthSecurity instead. type: basic 模式 (Schema) 的描述 每一种模式 (Schema), 都会有一个标题 (title) 和一段描述, 比如 : definitions: Person: title: Human description: A person which can be the user itself or one of his friend 属性的描述 比如 : 91

92 properties: firstname: description: first name 参数的描述 paths: /persons: post: - name: person in: body required: true description: The person to create. $ref: '#/definitions/person' username: name: username in: path required: true description: The person's username pagesize: name: pagesize in: query description: Number of persons returned 操作的概述 (summary) 描述和操作 ID(operationId) 一个操作 (Operation) 通常都会包含概述和描述信息 而且我们还可以添加一个关键字 operationid, 这个关键字通常用来指示服务提供者对这个操作的处理函数的函数名 比如 : 92

93 paths: /persons: - $ref: '#/parameters/useragent' get: summary: Gets some persons description: Returns a list containing all persons. The li st supports paging. operationid: searchusers 响应消息的描述 paths: /persons: - $ref: '#/parameters/useragent' get: '200': description: A list of Person Standard500ErrorResponse: description: An unexpected error occured 响应消息头的描述 93

94 headers: X-Rate-Limit-Remaining: description: How many calls consumer can do type: integer X-Rate-Limit-Reset: description: When rate limit will be reset format: date-time 标签的描述 我们在 API 文档的根路径下添加了 tags 的定义, 对于其中的每一个标签, 我们都 可以添加描述信息 : tags: - name: Persons description: Everything you need to handle users and friends 7.3 在描述中使用 Markdown 语法 在绝大部分的 description 中, 我们可以使用 GFM(Github Flavored Markdown) 语法 多行描述 使用符号 然后在新行中打一个 tab( 注意 :YAML 的 tab 是两个空格 ), 就可以 编辑多行描述, 比如 : 94

95 '/persons/{username}/collecting-items': - $ref: '#/parameters/username' - $ref: '#/parameters/useragent' get: summary: Gets a person's collecting items list description: Returns a list containing all items this person is looki ng for. The list supports paging 简单使用 GFM 比如我们要强调, 可以这样写 : externaldocs: description: **Complete** documentation describing how to use this API url: 带信息组的描述 95

96 CollectingItem: discriminator: itemtype required: - itemtype properties: itemtype: description: An item can be of different type: type definition Vinyl #/definitions/vinyl VHS #/definitions/vhs AudioCassette #/definitions/audiocassette enum: - AudioCassette - Vinyl - VHS 带代码的描述 96

97 swagger: '2.0' info: version: title: Simple API description: A simple API to learn how to write OpenAPI Specification. This file uses almost every single aspect of the [Open API S pecification]( This API will use JSON. JSON looks like this: ```JSON { "key": "value", "anotherkey": "anothervalue" } 97

98 ### 7.4 示例数据 (Examples) 我们已经知道了用 Schema 来描述参数和属性, 有的时候, 用示例数据更有表现了 我们 可以使用关键字 `example` 来给原子属性或者对象添加示例数据 #### 原子属性的示例数据 ```YAML properties: firstname: description: first name example: John # END #### lasttimeonline: description: The last time this person was connected to the service as a format: date-time readonly: true example: T12:36:58.014Z # END #### 对象属性的示例数据 98

99 Persons: title: Humans description: A list of users or friends required: - items properties: items: description: Array containg the list type: array minitems: 10 maxitems: 100 uniqueitems: true items: $ref: '#/definitions/person' example: - firstname: Robert lastname": Doe username": robdo dateofbirth: lasttimeonline: T14:36:58.014Z - firstname: Jane lastname: Doe username: jdoe123 dateofbirth: lasttimeonline: T19:23:59.014Z # END #### 定义的示例数据 跟普通属性一样, 定义的对象也能添加示例数据 : 99

100 MultilingualErrorMessage: title: MultiLingualMultiDeviceErrorMessage description: An multilingual error message (hashmap) with a long and a short description additionalproperties: $ref: '#/definitions/errormessage' properties: defaultlanguage: $ref: '#/definitions/errormessage' example: defaultlanguage: longmessage: We're deeply sorry but an error occured shortmessage: Error fr: longmessage: Nous sommes dã solã mais une erreur est su rvenu shortmessage: Erreur # END #### 响应消息的示例数据 我们甚至可以添加响应消息级别的示例数据 : '/persons/{username}/collecting-items': get: '200': examples: application/json: { "totalitems": 10, "totalpage": 4, 100

101 "pagesize": 3, "currentpage": 2, "items": [ { "itemtype": "Vinyl", "maxprice": 20, "imageid": " eb-4bac-b32e-cd5b7196 de71", "albumname": "Captain Future Original Soundt rack", "artist": "Yuji Ohno" }, { "itemtype": "VHS", "maxprice": 10, "imageid": "b74469bc-e6a1-4a90-858a-88ef ", "movietitle": "Star Crash", "director": "Luigi Cozzi" }, { "itemtype": "AudioCassette", "maxprice": 10, "imageid": "b74469bc-e6a1-4a90-858a-88ef ", "albumname": "Star Wars", "artist": "John Williams" } ] } # END #### '404': $ref: '#/responses/persondoesnotexistresponse' '500': $ref: '#/responses/standard500errorresponse' default: $ref: '#/responses/totallyunexpectedresponse' 101

102 7.4.5 示例数据的优先级 如果我们在各个级别 ( 比如参数 对象 定义 响应消息 ) 都添加了示例数据 支 持 OpenAPI 规范的各解析工具都是以最高级别的定义为准 7.5 标记为弃用 我们可以通过关键字 deprecated 置为 true 来标记接口的弃用状态, 比如 : /js-less-consumer-persons: - $ref: '#/parameters/useragent' post: summary: Creates a person description: For JS-less partners operationid: createuserjs deprecated: true 7.6 链接到外部文档 一般来说, 项目中不光只有一篇 API 文档, 还应该有些描述 application key, 测试用例, 操作链以及其他内容的文档, 这些文档一般是单独成篇的 如果在描述某个接口时, 我们想链接这些文档, 可以通过关键字 externaldoc 来添加, 例如 : externaldocs: description: Complete documentation describing how to use this API url: 102

103 /images: - $ref: '#/parameters/useragent' post: summary: Uploads an image description: Upload an image, will return an image id. operationid: storeimage externaldocs: description: How to upload media url: 第 8 章分而治之 根据前面几张的知识, 我们已经可以轻松的构建一个复杂的 API 文档了 可是作为一个学过 Clean Code 的程序员, 我们并不希望所有的接口 定义都在一个大而全的上帝文件里 这一章我们一起来学习拆分文件 8.1 JSON 指针 我们在第 2 章已经知道了怎么定义一个可重用的对象, 已经如何使用定义, 重温一 下 : 103

104 /persons/{username}: get: summary: Gets a person description: Returns a single person for its username. - name: username in: path required: true description: The person's username 200: description: A Person $ref: "#/definitions/person" 404: description: The Person does not exists. definitions: Person: required: - username properties: firstname: lastname: username: Persons: type: array items: $ref: "#/definitions/person" 在使用的时候我们这样写 :$ref: "#/definitions/person", $ref 就是 JSON 指针 ( 参见定义 RFC6901) 例子中的这个指针指向当前文档根路径( # ) 下的 definitions 下的 Person JSON 指针不仅可以指向当前文件, 还可以指向其他文件 104

105 8.2 基础拆分 引用本地文件 还是上面这个例子, 我们在当前文档的同一目录下, 新建的一个文件叫 person.yaml, 然后把 Person 的定义拆出来, 放在其中 Person: required: - username properties: firstname: lastname: username: 在当前文档中把引用 Person 定义的地方修改为 : $ref: "person.yaml#/person" 编辑器报错 把上面的代码放到 Swagger Editor 中编辑, 编辑器预览中可能会报错 : 提示找不到 person.yaml 文件 这是因为我们没有指定正确的编辑器的指针解析基 础路径 ( Pointer Resolution Base Path ) 105

106 解决的办法是 : 进入编辑器的 Preferences -> Preferences 菜单, 修改 Pointer Resolution Base Path 为 : 考虑到缓存的原因, 如果错误依然存在, 请刷新浏览器 文件夹 如果引用子文件夹下的文件, 我们可以这样写 : $ref: "folder/person.yaml#/person" 如果引用上级文件夹下的文件, 我们可以这样写 : Persons: type: array items: $ref: "../folder/person.yaml#/person" 引用远程文件 如果我们想引用一个远程文件, 应该怎么做呢? 可以这样写 : $ref: 但是需要注意的是 : 服务器必须提供跨域 (CORS) 访问服务 如果要通过本地服务器上的 8080 端口引用文件, 我们可以这样写 : $ref: " 考虑两种比较特别的情况 : 远端文件引用 " 本地文件 " 106

107 比如说, 我们引用了 : $ref: " ons" 这个远端文件 但是 persons.yaml 又引用了与它在同一目录下的 person.yaml 文件, 这个时候语法分析器会在 localhost:8080 上面找 person.yaml 文件, 而不会查找我们本地的 person.yaml 远端文件引用 更 远端文件如果理解了 这个例子, 我们就知道不管怎么引用, 都是在相对于被引用的文件下来进行查找的 整理一个文件中的多个定义 比如我们在一个文件中, 需要把定义分成几类, 可以这样做 : SomeDefinitions: Person: required: - username properties: firstname: lastname: username: OtherDefinitions: Persons: type: array items: $ref: "#/SomeDefinitions/Person" 107

108 Person 归属于 SomeDefinitions 这一类, Persons 归属 于 OtherDefinitions 这一类 那么我们在引用这两个定义时, 分别应该这样书 写 : $ref: "definitions.yaml#/otherdefinitions/persons" $ref: "definitions.yaml#/somedefinitions/person" 有点像命名空间的概念 8.3 实战切分的思路 结构化切分思路 : 先把 API 文档的头部 info 切下来, 放在 info.yaml, 然后分别切分 paths.yaml, definitions.yaml, responses.yaml, parameters. yaml 等文件, 最后合并到 main.yaml ; 分层切分思路 : 分别按照功能和层次, 将文件切分为 base.yaml 或 common.yaml, 然后是各个模块的 xxx-paths.yaml, 然后是各个定义的 xxx-definitions.yaml 其他思路 需要注意的是, 不管怎么切分, 有一个原则必须谨记 : 切分出来的子文档, 必须遵循 OpenAPI 规范, 能够通过编辑器的校验, 不然切分得再漂亮也是徒劳 The END??? NO! 接下来, 就看你的了! 附录 108

109 Arnaud Lauret 大神为了简化 OpenAPI 规范的阅读, 维护了一个 openapispecification-visual-documentation 的项目, 通过动态导图的方式把规范完整呈 现, 懒人必备 点击此处查看 109

Important Notice SUNPLUS TECHNOLOGY CO. reserves the right to change this documentation without prior notice. Information provided by SUNPLUS TECHNOLO

Important Notice SUNPLUS TECHNOLOGY CO. reserves the right to change this documentation without prior notice. Information provided by SUNPLUS TECHNOLO Car DVD New GUI IR Flow User Manual V0.1 Jan 25, 2008 19, Innovation First Road Science Park Hsin-Chu Taiwan 300 R.O.C. Tel: 886-3-578-6005 Fax: 886-3-578-4418 Web: www.sunplus.com Important Notice SUNPLUS

More information

通过Hive将数据写入到ElasticSearch

通过Hive将数据写入到ElasticSearch 我在 使用 Hive 读取 ElasticSearch 中的数据 文章中介绍了如何使用 Hive 读取 ElasticSearch 中的数据, 本文将接着上文继续介绍如何使用 Hive 将数据写入到 ElasticSearch 中 在使用前同样需要加入 elasticsearch-hadoop-2.3.4.jar 依赖, 具体请参见前文介绍 我们先在 Hive 里面建个名为 iteblog 的表,

More information

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc References (Section 5.2) Hsuan-Tien Lin Deptartment of CSIE, NTU OOP Class, March 15-16, 2010 H.-T. Lin (NTU CSIE) References OOP 03/15-16/2010 0 / 22 Fun Time (1) What happens in memory? 1 i n t i ; 2

More information

59 1 CSpace 2 CSpace CSpace URL CSpace 1 CSpace URL 2 Lucene 3 ID 4 ID Web 1. 2 CSpace LireSolr 3 LireSolr 3 Web LireSolr ID

59 1 CSpace 2 CSpace CSpace URL CSpace 1 CSpace URL 2 Lucene 3 ID 4 ID Web 1. 2 CSpace LireSolr 3 LireSolr 3 Web LireSolr ID 58 2016. 14 * LireSolr LireSolr CEDD Ajax CSpace LireSolr CEDD Abstract In order to offer better image support services it is necessary to extend the image retrieval function of our institutional repository.

More information

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7.

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes 包管理理 工具 Helm 蔺礼强 Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes

More information

「人名權威檔」資料庫欄位建置表

「人名權威檔」資料庫欄位建置表 ( version 0.2) 1 3 3 3 3 5 6 9.... 11 Entities - Relationship Model..... 12 13 14 16 2 ( ) Int Varchar Text byte byte byte Id Int 20 Name Surname Varchar 20 Forename Varchar 20 Alternate Type Varchar 10

More information

( Version 0.4 ) 1

( Version 0.4 ) 1 ( Version 0.4 ) 1 3 3.... 3 3 5.... 9 10 12 Entities-Relationship Model. 13 14 15.. 17 2 ( ) version 0.3 Int TextVarchar byte byte byte 3 Id Int 20 Name Surname Varchar 20 Forename Varchar 20 Alternate

More information

Microsoft Word - template.doc

Microsoft Word - template.doc HGC efax Service User Guide I. Getting Started Page 1 II. Fax Forward Page 2 4 III. Web Viewing Page 5 7 IV. General Management Page 8 12 V. Help Desk Page 13 VI. Logout Page 13 Page 0 I. Getting Started

More information

WWW PHP Comments Literals Identifiers Keywords Variables Constants Data Types Operators & Expressions 2

WWW PHP Comments Literals Identifiers Keywords Variables Constants Data Types Operators & Expressions 2 WWW PHP 2003 1 Comments Literals Identifiers Keywords Variables Constants Data Types Operators & Expressions 2 Comments PHP Shell Style: # C++ Style: // C Style: /* */ $value = $p * exp($r * $t); # $value

More information

untitled

untitled ArcGIS Server Web services Web services Application Web services Web Catalog ArcGIS Server Web services 6-2 Web services? Internet (SOAP) :, : Credit card authentication, shopping carts GIS:, locator services,

More information

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii 前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii C# 7 More Effective C# C# C# C# C# C# Common Language Runtime CLR just-in-time

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

IBM Rational ClearQuest Client for Eclipse 1/ IBM Rational ClearQuest Client for Ecl

IBM Rational ClearQuest Client for Eclipse   1/ IBM Rational ClearQuest Client for Ecl 1/39 Balaji Krish,, IBM Nam LeIBM 2005 4 15 IBM Rational ClearQuest ClearQuest Eclipse Rational ClearQuest / Eclipse Clien Rational ClearQuest Rational ClearQuest Windows Web Rational ClearQuest Client

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

簡報技巧

簡報技巧 2 Q & A 4 7 Presenter Audienc e 7 10 / 11 7 / 11 / 7 55 11 / 7 55 38 11 12 13 14 Q & A 1. : 1. : 1. : / 5W Who What When Where Why 1. : / 5W Who What When 5W2H How to do How much Where Why 1.

More information

2 SGML, XML Document Traditional WYSIWYG Document Content Presentation Content Presentation Structure Structure? XML/SGML 3 2 SGML SGML Standard Gener

2 SGML, XML Document Traditional WYSIWYG Document Content Presentation Content Presentation Structure Structure? XML/SGML 3 2 SGML SGML Standard Gener SGML HTML XML 1 SGML XML Extensible Markup Language XML SGML Standard Generalized Markup Language, ISO 8879, SGML HTML ( Hypertext Markup Language HTML) (Markup Language) (Tag) < > Markup (ISO) 1986 SGML

More information

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM CHAPTER 6 SQL SQL SQL 6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM 3. 1986 10 ANSI SQL ANSI X3. 135-1986

More information

IP505SM_manual_cn.doc

IP505SM_manual_cn.doc IP505SM 1 Introduction 1...4...4...4...5 LAN...5...5...6...6...7 LED...7...7 2...9...9...9 3...11...11...12...12...12...14...18 LAN...19 DHCP...20...21 4 PC...22...22 Windows...22 TCP/IP -...22 TCP/IP

More information

WWW PHP

WWW PHP WWW PHP 2003 1 2 function function_name (parameter 1, parameter 2, parameter n ) statement list function_name sin, Sin, SIN parameter 1, parameter 2, parameter n 0 1 1 PHP HTML 3 function strcat ($left,

More information

管道建模基础.ppt

管道建模基础.ppt AVEVA 2004.11.4 Pdms (database hierarchy) (PipeworkModelling) PIPE WORLD BRANCH PDMS FLANGE,Elbow.. SITE Pipe routing is probably the activity that consumes most time on any large project and it is also

More information

概述

概述 OPC Version 1.6 build 0910 KOSRDK Knight OPC Server Rapid Development Toolkits Knight Workgroup, eehoo Technology 2002-9 OPC 1...4 2 API...5 2.1...5 2.2...5 2.2.1 KOS_Init...5 2.2.2 KOS_InitB...5 2.2.3

More information

Windows XP

Windows XP Windows XP What is Windows XP Windows is an Operating System An Operating System is the program that controls the hardware of your computer, and gives you an interface that allows you and other programs

More information

SL2511 SR Plus 操作手冊_單面.doc

SL2511 SR Plus 操作手冊_單面.doc IEEE 802.11b SL-2511 SR Plus SENAO INTERNATIONAL CO., LTD www.senao.com - 1 - - 2 - .5 1-1...5 1-2...6 1-3...6 1-4...7.9 2-1...9 2-2 IE...11 SL-2511 SR Plus....13 3-1...13 3-2...14 3-3...15 3-4...16-3

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

Microsoft PowerPoint - ch6 [相容模式]

Microsoft PowerPoint - ch6 [相容模式] UiBinder wzyang@asia.edu.tw UiBinder Java GWT UiBinder XML UI i18n (widget) 1 2 UiBinder HelloWidget.ui.xml: UI HelloWidgetBinder HelloWidget.java XML UI Owner class ( Composite ) UI XML UiBinder: Owner

More information

CDWA Mapping. 22 Dublin Core Mapping

CDWA Mapping. 22 Dublin Core Mapping (version 0.23) 1 3... 3 3 3 5 7 10 22 CDWA Mapping. 22 Dublin Core Mapping. 24 26 28 30 33 2 3 X version 0.2 ( ) 4 Int VarcharText byte byte byte Id Int 10 Management Main Code Varchar 30 Code Original

More information

Microsoft Word - Final Exam Review Packet.docx

Microsoft Word - Final Exam Review Packet.docx Do you know these words?... 3.1 3.5 Can you do the following?... Ask for and say the date. Use the adverbial of time correctly. Use Use to ask a tag question. Form a yes/no question with the verb / not

More information

epub83-1

epub83-1 C++Builder 1 C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r 1.1 1.1.1 1-1 1. 1-1 1 2. 1-1 2 A c c e s s P a r a d o x Visual FoxPro 3. / C / S 2 C + + B u i l d e r / C

More information

RPC SOAP REST API API HTTP JSON XML PHP PHP PHP PHP PHP HTTP request/response cycle HTTP HTTP verbs headers Cookies JSON XML PHP RPC SOAP RESTful HTTP

RPC SOAP REST API API HTTP JSON XML PHP PHP PHP PHP PHP HTTP request/response cycle HTTP HTTP verbs headers Cookies JSON XML PHP RPC SOAP RESTful HTTP RPC SOAP REST API API HTTP JSON XML PHP PHP PHP PHP PHP HTTP request/response cycle HTTP HTTP verbs headers Cookies JSON XML PHP RPC SOAP RESTful HTTP API API 前言 vii 第一章 HTTP HTTP HyperText Transfer Protocol

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

}; "P2VTKNvTAnYNwBrqXbgxRSFQs6FTEhNJ", " " string imagedata; if(0!= read_image("a.jpg",imagedata)) { return -1; } string rsp; ytopen_sdk m_sd

}; P2VTKNvTAnYNwBrqXbgxRSFQs6FTEhNJ,   string imagedata; if(0!= read_image(a.jpg,imagedata)) { return -1; } string rsp; ytopen_sdk m_sd tencentyun-youtu c++ sdk for 腾讯云智能优图服务 & 腾讯优图开放平台 安装 运行环境 Linux 依赖项 - curl-7.40.0, 获取更新版本 https://github.com/bagder/curl - openssl-1.0.1k, 获取更新版本 https://github.com/openssl/openssl 构建工程 工程采用 CMake 构建 1.

More information

Computer Architecture

Computer Architecture ECE 3120 Computer Systems Assembly Programming Manjeera Jeedigunta http://blogs.cae.tntech.edu/msjeedigun21 Email: msjeedigun21@tntech.edu Tel: 931-372-6181, Prescott Hall 120 Prev: Basic computer concepts

More information

錄...1 說...2 說 說...5 六 率 POST PAY PREPAY DEPOSIT 更

錄...1 說...2 說 說...5 六 率 POST PAY PREPAY DEPOSIT 更 AX5000 Version 1.0 2006 年 9 錄...1 說...2 說...3...4 說...5 六...6 6.1 率...7 6.2 POST PAY...8 6.3 PREPAY DEPOSIT...9 6.4...10 6.5...11 更...12...12 LCD IC LED Flash 更 兩 RJ11 ( ) DC ON OFF ON 狀 狀 更 OFF 復 狀 說

More information

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页

一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 第 1 页共 32 页 crm Mobile V1.0 for IOS 用户手册 一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 二 crm Mobile 界面介绍 : 第 3 页共 32 页 三 新建 (New) 功能使用说明 1 选择产品 第 4 页共 32 页 2 填写问题的简要描述和详细描述 第 5 页共

More information

Improved Preimage Attacks on AES-like Hash Functions: Applications to Whirlpool and Grøstl

Improved Preimage Attacks on AES-like Hash Functions: Applications to Whirlpool and Grøstl SKLOIS (Pseudo) Preimage Attack on Reduced-Round Grøstl Hash Function and Others Shuang Wu, Dengguo Feng, Wenling Wu, Jian Guo, Le Dong, Jian Zou March 20, 2012 Institute. of Software, Chinese Academy

More information

3.1 num = 3 ch = 'C' 2

3.1 num = 3 ch = 'C' 2 Java 1 3.1 num = 3 ch = 'C' 2 final 3.1 final : final final double PI=3.1415926; 3 3.2 4 int 3.2 (long int) (int) (short int) (byte) short sum; // sum 5 3.2 Java int long num=32967359818l; C:\java\app3_2.java:6:

More information

coverage2.ppt

coverage2.ppt Satellite Tool Kit STK/Coverage STK 82 0715 010-68745117 1 Coverage Definition Figure of Merit 2 STK Basic Grid Assets Interval Description 3 Grid Global Latitude Bounds Longitude Lines Custom Regions

More information

基于ECO的UML模型驱动的数据库应用开发1.doc

基于ECO的UML模型驱动的数据库应用开发1.doc ECO UML () Object RDBMS Mapping.Net Framework Java C# RAD DataSetOleDbConnection DataGrod RAD Client/Server RAD RAD DataReader["Spell"].ToString() AObj.XXX bug sql UML OR Mapping RAD Lazy load round trip

More information

Logitech Wireless Combo MK45 English

Logitech Wireless Combo MK45 English Logitech Wireless Combo MK45 Setup Guide Logitech Wireless Combo MK45 English................................................................................... 7..........................................

More information

C/C++程序设计 - 字符串与格式化输入/输出

C/C++程序设计 - 字符串与格式化输入/输出 C/C++ / Table of contents 1. 2. 3. 4. 1 i # include # include // density of human body : 1. 04 e3 kg / m ^3 # define DENSITY 1. 04 e3 int main ( void ) { float weight, volume ; int

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

Olav Lundström MicroSCADA Pro Marketing & Sales 2005 ABB - 1-1MRS755673

Olav Lundström MicroSCADA Pro Marketing & Sales 2005 ABB - 1-1MRS755673 Olav Lundström MicroSCADA Pro Marketing & Sales 2005 ABB - 1 - Contents MicroSCADA Pro Portal Marketing and sales Ordering MicroSCADA Pro Partners Club 2005 ABB - 2 - MicroSCADA Pro - Portal Imagine that

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information

<4D6963726F736F667420576F7264202D2032303130C4EAC0EDB9A4C0E04142BCB6D4C4B6C1C5D0B6CFC0FDCCE2BEABD1A15F325F2E646F63>

<4D6963726F736F667420576F7264202D2032303130C4EAC0EDB9A4C0E04142BCB6D4C4B6C1C5D0B6CFC0FDCCE2BEABD1A15F325F2E646F63> 2010 年 理 工 类 AB 级 阅 读 判 断 例 题 精 选 (2) Computer mouse How does the mouse work? We have to start at the bottom, so think upside down for now. It all starts with mouse ball. As the mouse ball in the bottom

More information

VIDEOJET connect 7000 VJC-7000-90 zh- CHS Operation Manual VIDEOJET connect 7000 zh-chs 3 目 录 1 浏 览 器 连 接 7 1.1 系 统 要 求 7 1.2 建 立 连 接 7 1.2.1 摄 像 机 中 的 密 码 保 护 7 1.3 受 保 护 的 网 络 7 2 系 统 概 述 8 2.1 实 况

More information

PowerPoint Presentation

PowerPoint Presentation TOEFL Practice Online User Guide Revised September 2009 In This Guide General Tips for Using TOEFL Practice Online Directions for New Users Directions for Returning Users 2 General Tips To use TOEFL Practice

More information

Microsoft Word - 苹果脚本跟我学.doc

Microsoft Word - 苹果脚本跟我学.doc AppleScript for Absolute Starters 2 2 3 0 5 1 6 2 10 3 I 13 4 15 5 17 6 list 20 7 record 27 8 II 32 9 34 10 36 11 44 12 46 13 51 14 handler 57 15 62 63 3 AppleScript AppleScript AppleScript AppleScript

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

國家圖書館典藏電子全文

國家圖書館典藏電子全文 EAI EAI Middleware EAI 3.1 EAI EAI Client/Server Internet,www,Jav a 3.1 EAI Message Brokers -Data Transformation Business Rule XML XML 37 3.1 XML XML XML EAI XML 1. XML XML Java Script VB Script Active

More information

ebook140-8

ebook140-8 8 Microsoft VPN Windows NT 4 V P N Windows 98 Client 7 Vintage Air V P N 7 Wi n d o w s NT V P N 7 VPN ( ) 7 Novell NetWare VPN 8.1 PPTP NT4 VPN Q 154091 M i c r o s o f t Windows NT RAS [ ] Windows NT4

More information

Junos Pulse Mobile Security R1 2012, Juniper Networks, Inc.

Junos Pulse Mobile Security R1 2012, Juniper Networks, Inc. Junos Pulse Mobile Security 4.0 2012 6 R1 2012, Juniper Networks, Inc. Junos Pulse Mobile Security Juniper Networks, Inc. 1194 North Mathilda Avenue Sunnyvale, California 94089 408-745-2000 www.juniper.net

More information

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取将导致上次获取的 access_token 失效 接入方可以使用 AppID 和 AppSecret

More information

untitled

untitled 1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override

More information

WebSphere Studio Application Developer IBM Portal Toolkit... 2/21 1. WebSphere Portal Portal WebSphere Application Server stopserver.bat -configfile..

WebSphere Studio Application Developer IBM Portal Toolkit... 2/21 1. WebSphere Portal Portal WebSphere Application Server stopserver.bat -configfile.. WebSphere Studio Application Developer IBM Portal Toolkit... 1/21 WebSphere Studio Application Developer IBM Portal Toolkit Portlet Doug Phillips (dougep@us.ibm.com),, IBM Developer Technical Support Center

More information

ebook140-9

ebook140-9 9 VPN VPN Novell BorderManager Windows NT PPTP V P N L A V P N V N P I n t e r n e t V P N 9.1 V P N Windows 98 Windows PPTP VPN Novell BorderManager T M I P s e c Wi n d o w s I n t e r n e t I S P I

More information

CHAPTER 1

CHAPTER 1 CHAPTER 1 1-1 System Development Life Cycle; SDLC SDLC Waterfall Model Shelly 1995 1. Preliminary Investigation 2. System Analysis 3. System Design 4. System Development 5. System Implementation and Evaluation

More information

USPTO Academic research Corporate needs Global/International Inventors Libraries News Media/Publication Patent Attorney or Agent USPTO e (ebusiness Ce

USPTO Academic research Corporate needs Global/International Inventors Libraries News Media/Publication Patent Attorney or Agent USPTO e (ebusiness Ce I 2002.03.27 2 http://www.uspto.gov/ http://www.wipo.org/ http://ipdl.wipo.int/ esp@cenet http://www.european-patent-office.org/ http://ep.espacenet.com/ http://www.cpo.cn.net/ 3 4 USPTO USPTO First time

More information

使用Cassandra和Spark 2.0实现Rest API服务

使用Cassandra和Spark 2.0实现Rest API服务 使用 Cassandra 和 Spark 2.0 实现 Rest API 服务 在这篇文章中, 我将介绍如何在 Spark 中使用 Akkahttp 并结合 Cassandra 实现 REST 服务, 在这个系统中 Cassandra 用于数据的存储 我们已经见识到 Spark 的威力, 如果和 Cassandra 正确地结合可以实现更强大的系统 我们先创建一个 build.sbt 文件, 内容如下

More information

Value Chain ~ (E-Business RD / Pre-Sales / Consultant) APS, Advanc

Value Chain ~ (E-Business RD / Pre-Sales / Consultant) APS, Advanc Key @ Value Chain fanchihmin@yahoo.com.tw 1 Key@ValueChain 1994.6 1996.6 2000.6 2000.10 ~ 2004.10 (E- RD / Pre-Sales / Consultant) APS, Advanced Planning & Scheduling CDP, Collaborative Demand Planning

More information

untitled

untitled 2006 6 Geoframe Geoframe 4.0.3 Geoframe 1.2 1 Project Manager Project Management Create a new project Create a new project ( ) OK storage setting OK (Create charisma project extension) NO OK 2 Edit project

More information

Microsoft Word - HC20138_2010.doc

Microsoft Word - HC20138_2010.doc Page: 1 of 7 Date: April 26, 2010 WINMATE COMMUNICATION INC. 9 F, NO. 111-6, SHING-DE RD., SAN-CHUNG CITY, TAIPEI, TAIWAN, R.O.C. The following merchandise was submitted and identified by the vendor as:

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

Gassama Abdoul Gadiri University of Science and Technology of China A dissertation for master degree Ordinal Probit Regression Model and Application in Credit Rating for Users of Credit Card Author :

More information

Chapter 24 DC Battery Sizing

Chapter 24  DC Battery Sizing 26 (Battery Sizing & Discharge Analysis) - 1. 2. 3. ETAP PowerStation IEEE 485 26-1 ETAP PowerStation 4.7 IEEE 485 ETAP PowerStation 26-2 ETAP PowerStation 4.7 26.1 (Study Toolbar) / (Run Battery Sizing

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

(Load Project) (Save Project) (OffLine Mode) (Help) Intel Hex Motor

(Load Project) (Save Project) (OffLine Mode) (Help) Intel Hex Motor 1 4.1.1.1 (Load) 14 1.1 1 4.1.1.2 (Save) 14 1.1.1 1 4.1.2 (Buffer) 16 1.1.2 1 4.1.3 (Device) 16 1.1.3 1 4.1.3.1 (Select Device) 16 2 4.1.3.2 (Device Info) 16 2.1 2 4.1.3.3 (Adapter) 17 2.1.1 CD-ROM 2 4.1.4

More information

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢   学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 Email: 51141201063@ecnu.cn 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Java 类型 引用 不可变类型 对象存储位置 作用域 OOP

More information

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F 1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET 2.0 2.0.NET Framework.NET Framework 2.0 ( 3).NET Framework 2.0.NET Framework ( System ) o o o o o o Boxing UnBoxing() o

More information

1 2 <CAHhX17dox1o7cv63SgXVrJRs

1 2  <CAHhX17dox1o7cv63SgXVrJRs ParaView 2019 1 21 1 1.1 ParaView [1] 2001-2018 ParaView Bug 2018 ParaView ParaView ParaView [5, 3] ParaView https://public.kitware.com/pipermail/paraview/ 1.2 URL URL Javascript document.queryselectall()

More information

1

1 DOCUMENTATION FOR FAW-VW Auto Co., Ltd. Sales & Service Architecture Concept () () Version 1.0.0.1 Documentation FAW-VW 1 61 1...4 1.1...4 2...4 3...4 3.1...4 3.2...5 3.3...5 4...5 4.1 IP...5 4.2 DNSDNS...6

More information

數位圖書館/博物館相關標準 2

數位圖書館/博物館相關標準 2 數 2 立 XML (Extensibility) XML 行 (Self-description) (Structure) XML (Validation) XML DTD 行 XML 列 XML-Language SGML without tears Self-describing Documents Well-formed and Valid Documents XML-Link Power

More information

Microsoft Word - CX VMCO 3 easy step v1.doc

Microsoft Word - CX VMCO 3 easy step v1.doc Abacus Fully Automated Process of VMCO on CX, KA, CPH & KAH 16 Nov 2009 To streamline the VMCO handling on CX, KA, CPH & KAH, Abacus is pleased to inform you that manual submission of VMCO to CX/KA/CPH/KAH

More information

<4D6963726F736F667420506F776572506F696E74202D20C8EDBCFEBCDCB9B9CAA6D1D0D0DEBDB2D7F92E707074>

<4D6963726F736F667420506F776572506F696E74202D20C8EDBCFEBCDCB9B9CAA6D1D0D0DEBDB2D7F92E707074> 软 件 架 构 师 研 修 讲 座 胡 协 刚 软 件 架 构 师 UML/RUP 专 家 szjinco@public.szptt.net.cn 中 国 软 件 架 构 师 网 东 软 培 训 中 心 小 故 事 : 七 人 分 粥 当 前 软 件 团 队 的 开 发 现 状 和 面 临 的 问 题 软 件 项 目 的 特 点 解 决 之 道 : 从 瀑 布 模 型 到 迭 代 模 型 解 决 项

More information

States and capital package

States and capital package : 1 Students are required to know 50 states and capitals and their geological locations. This is an independent working packet to learn about 50 states and capital. Students are asked to fulfill 4 activities

More information

Guide to Install SATA Hard Disks

Guide to Install SATA Hard Disks SATA RAID 1. SATA. 2 1.1 SATA. 2 1.2 SATA 2 2. RAID (RAID 0 / RAID 1 / JBOD).. 4 2.1 RAID. 4 2.2 RAID 5 2.3 RAID 0 6 2.4 RAID 1.. 10 2.5 JBOD.. 16 3. Windows 2000 / Windows XP 20 1. SATA 1.1 SATA Serial

More information

Oracle高级复制配置手册_业务广告_.doc

Oracle高级复制配置手册_业务广告_.doc Oracle 高 级 复 制 配 置 手 册 作 者 : 铁 钉 Q Q: 5979404 MSN: nail.cn@msn.com Mail: nail.cn@msn.com Blog: http://nails.blog.51cto.com Materialized View Replication 复 制 模 式 实 现 了 单 主 机 对 多 个 复 制 站 点 的 数 据 同 步. 在 主

More information

Microsoft Word - TIP006SCH Uni-edit Writing Tip - Presentperfecttenseandpasttenseinyourintroduction readytopublish

Microsoft Word - TIP006SCH Uni-edit Writing Tip - Presentperfecttenseandpasttenseinyourintroduction readytopublish 我 难 度 : 高 级 对 们 现 不 在 知 仍 道 有 听 影 过 响 多 少 那 次 么 : 研 英 究 过 文 论 去 写 文 时 作 的 表 技 引 示 巧 言 事 : 部 情 引 分 发 言 该 生 使 在 中 用 过 去, 而 现 在 完 成 时 仅 表 示 事 情 发 生 在 过 去, 并 的 哪 现 种 在 时 完 态 成 呢 时? 和 难 过 道 去 不 时 相 关? 是 所 有

More information

Knowledge and its Place in Nature by Hilary Kornblith

Knowledge and its Place in Nature by Hilary Kornblith Deduction by Daniel Bonevac Chapter 7 Quantified Natural Deduction Quantified Natural Deduction As with truth trees, natural deduction in Q depends on the addition of some new rules to handle the quantifiers.

More information

穨control.PDF

穨control.PDF TCP congestion control yhmiu Outline Congestion control algorithms Purpose of RFC2581 Purpose of RFC2582 TCP SS-DR 1998 TCP Extensions RFC1072 1988 SACK RFC2018 1996 FACK 1996 Rate-Halving 1997 OldTahoe

More information

<4D6963726F736F667420576F7264202D205F4230365FB942A5CEA668B443C5E9BB73A740B5D8A4E5B8C9A552B1D0A7F75FA6BFB1A4ACFC2E646F63>

<4D6963726F736F667420576F7264202D205F4230365FB942A5CEA668B443C5E9BB73A740B5D8A4E5B8C9A552B1D0A7F75FA6BFB1A4ACFC2E646F63> 運 用 多 媒 體 製 作 華 文 補 充 教 材 江 惜 美 銘 傳 大 學 應 用 中 文 系 chm248@gmail.com 摘 要 : 本 文 旨 在 探 究 如 何 運 用 多 媒 體, 結 合 文 字 聲 音 圖 畫, 製 作 華 文 補 充 教 材 當 我 們 在 進 行 華 文 教 學 時, 往 往 必 須 透 過 教 案 設 計, 並 製 作 補 充 教 材, 方 能 使 教 學

More information

C/C++ - 文件IO

C/C++ - 文件IO C/C++ IO Table of contents 1. 2. 3. 4. 1 C ASCII ASCII ASCII 2 10000 00100111 00010000 31H, 30H, 30H, 30H, 30H 1, 0, 0, 0, 0 ASCII 3 4 5 UNIX ANSI C 5 FILE FILE 6 stdio.h typedef struct { int level ;

More information

Bus Hound 5

Bus Hound 5 Bus Hound 5.0 ( 1.0) 21IC 2007 7 BusHound perisoft PC hound Bus Hound 6.0 5.0 5.0 Bus Hound, IDE SCSI USB 1394 DVD Windows9X,WindowsMe,NT4.0,2000,2003,XP XP IRP Html ZIP SCSI sense USB Bus Hound 1 Bus

More information

Microsoft PowerPoint - Performance Analysis of Video Streaming over LTE using.pptx

Microsoft PowerPoint - Performance Analysis of Video Streaming over LTE using.pptx ENSC 427 Communication Networks Spring 2016 Group #2 Project URL: http://www.sfu.ca/~rkieu/ensc427_project.html Amer, Zargham 301149920 Kieu, Ritchie 301149668 Xiao, Lei 301133381 1 Roadmap Introduction

More information

A9RF716.tmp

A9RF716.tmp 1 PART I 1 2 3 4 5 6 7 8 Docker Docker Image Container Repository Docker le Docker Docker 8 1 Docker Linux 2 Docker Docker 3 5 Docker 6 Docker volume 7 8 Docker le Docker le 1 C H A P T E R 1 CPU Data

More information

Office Office Office Microsoft Word Office Office Azure Office One Drive 2 app 3 : [5] 3, :, [6]; [5], ; [8], [1], ICTCLAS(Institute of Computing Tech

Office Office Office Microsoft Word Office Office Azure Office One Drive 2 app 3 : [5] 3, :, [6]; [5], ; [8], [1], ICTCLAS(Institute of Computing Tech - OfficeCoder 1 2 3 4 1,2,3,4 xingjiarong@mail.sdu.edu.cn 1 xuchongyang@mail.sdu.edu.cn 2 sun.mc@outlook.com 3 luoyuanhang@mail.sdu.edu.cn 4 Abstract. Microsoft Word 2013 Word 2013 Office Keywords:,, HTML5,

More information

第1章 簡介

第1章 簡介 EAN.UCCThe Global Language of Business 4 512345 678906 > 0 12345 67890 5 < > 1 89 31234 56789 4 ( 01) 04601234567893 EAN/UCC-14: 15412150000151 EAN/UCC-13: 5412150000161 EAN/UCC-14: 25412150000158 EAN/UCC-13:

More information

Microsoft PowerPoint - STU_EC_Ch08.ppt

Microsoft PowerPoint - STU_EC_Ch08.ppt 樹德科技大學資訊工程系 Chapter 8: Counters Shi-Huang Chen Fall 2010 1 Outline Asynchronous Counter Operation Synchronous Counter Operation Up/Down Synchronous Counters Design of Synchronous Counters Cascaded Counters

More information

2 response personnel to speed up the rescue operations after various natural or man-made disasters. Keywords: SMS, Database, Disaster

2 response personnel to speed up the rescue operations after various natural or man-made disasters. Keywords: SMS, Database, Disaster Journal of Information, Technology and Society 2004(1) 1 Implementation of Emergency Response SMS System Using DBMS a b c d 1 106 s1428032@ntut.edu.tw, loveru@geoit.ws, aponson@yahoo.com.tw, waltchen@ntut.edu.tw

More information

LEETCODE leetcode.com 一 个 在 线 编 程 网 站, 收 集 了 IT 公 司 的 面 试 题, 包 括 算 法, 数 据 库 和 shell 算 法 题 支 持 多 种 语 言, 包 括 C, C++, Java, Python 等 2015 年 3 月 份 加 入 了 R

LEETCODE leetcode.com 一 个 在 线 编 程 网 站, 收 集 了 IT 公 司 的 面 试 题, 包 括 算 法, 数 据 库 和 shell 算 法 题 支 持 多 种 语 言, 包 括 C, C++, Java, Python 等 2015 年 3 月 份 加 入 了 R 用 RUBY 解 LEETCODE 算 法 题 RUBY CONF CHINA 2015 By @quakewang LEETCODE leetcode.com 一 个 在 线 编 程 网 站, 收 集 了 IT 公 司 的 面 试 题, 包 括 算 法, 数 据 库 和 shell 算 法 题 支 持 多 种 语 言, 包 括 C, C++, Java, Python 等 2015 年 3 月 份

More information

第一章 出口退税制改革的内容

第一章  出口退税制改革的内容 密 级 学 号 2 0 0 1 0 3 2 9 毕 业 设 计 ( 论 文 ) 出 口 退 税 制 改 革 对 我 国 出 口 的 影 响 院 ( 系 部 ): 经 济 管 理 学 院 姓 名 : 王 晓 年 级 : 2001 级 专 业 : 国 际 经 济 与 贸 易 指 导 教 师 : 杜 秀 芳 教 师 职 称 : 讲 师 2005 年 6 月 10 日 北 京 北 京 石 油 化 工 学 院

More information

《红楼梦》中茗烟与李贵的对比分析

《红楼梦》中茗烟与李贵的对比分析 第 13 卷 第 2 期 中 南 大 学 学 报 ( 社 会 科 学 版 ) Vol.13 No.2 2007 年 4 月 J. CENT. SOUTH UNIV. (SOCIAL SCIENCE) Apr. 2007 红 楼 梦 茗 烟 与 李 贵 形 象 比 较 研 究 李 鸿 渊, 奉 旨 亨 ( 湖 南 科 技 大 学 人 文 学 院, 湖 南 湘 潭,411201) 摘 要 : 茗 烟 与

More information

Microsoft PowerPoint - AWOL - Acrobat Windows Outlook.ppt [Compatibility Mode]

Microsoft PowerPoint - AWOL - Acrobat Windows Outlook.ppt [Compatibility Mode] AWOL Windows - Tips & Tricks Resolution, color depth & refresh rate Background color Service packs Disk cleanup (cleanmgr) Disk defragmentation AWOL Windows Resolution, Color Depth & Refresh Rate The main

More information

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6 www.brainysoft.net 1.JasperReport ireport...4 1.1 JasperReport...4 1.2 ireport...4 2....4 2.1 JDK...4 2.1.1 JDK...4 2.1.2 JDK...5 2.1.3 JDK...5 2.2 ant...6 2.2.1 ant...6 2.2.2 ant...6 2.3 JasperReport...7

More information

Microsoft Word - 3D手册2.doc

Microsoft Word - 3D手册2.doc 第 一 章 BLOCK 前 处 理 本 章 纲 要 : 1. BLOCK 前 处 理 1.1. 创 建 新 作 业 1.2. 设 定 模 拟 控 制 参 数 1.3. 输 入 对 象 数 据 1.4. 视 图 操 作 1.5. 选 择 点 1.6. 其 他 显 示 窗 口 图 标 钮 1.7. 保 存 作 业 1.8. 退 出 DEFORMTM3D 1 1. BLOCK 前 处 理 1.1. 创 建

More information

入學考試網上報名指南

入學考試網上報名指南 入 學 考 試 網 上 報 名 指 南 On-line Application Guide for Admission Examination 16/01/2015 University of Macau Table of Contents Table of Contents... 1 A. 新 申 請 網 上 登 記 帳 戶 /Register for New Account... 2 B. 填

More information

0000 00 10701 0000000000 XX000.00 0000 00 Dissertation Title in English A dissertation submitted to XIDIAN UNIVERSITY in partial fulfillment of the requirements for the degree of Doctor By Firstname

More information

2/80 2

2/80 2 2/80 2 3/80 3 DSP2400 is a high performance Digital Signal Processor (DSP) designed and developed by author s laboratory. It is designed for multimedia and wireless application. To develop application

More information

C/C++ - 字符输入输出和字符确认

C/C++ - 字符输入输出和字符确认 C/C++ Table of contents 1. 2. getchar() putchar() 3. (Buffer) 4. 5. 6. 7. 8. 1 2 3 1 // pseudo code 2 read a character 3 while there is more input 4 increment character count 5 if a line has been read,

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 The BitCoin Scripting Language 交易实例 交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d

More information