1. 简介
本文是 RAML(RESTful API Modeling Language)系列教程的第四篇,主要介绍 **如何通过 注解(annotations)为 RAML API 规范定义自定义属性**。这个过程也称为对规范元数据的扩展。
注解可以为 RAML 处理工具提供额外的扩展信息,这些信息超出了 RAML 官方语言本身的定义范围。
2. 声明注解类型
我们可以通过顶层的 annotationTypes
属性来声明一个或多个 注解类型。
最简单的情况下,只需要指定 注解类型名称,此时它的值类型默认为字符串:
annotationTypes:
simpleImplicitStringValueType:
这等价于显式声明如下:
annotationTypes:
simpleExplicitStringValueType:
type: string
在更复杂的情况下,注解类型可以包含一个值对象,也就是所谓的 注解类型声明。
此时,注解类型使用与 数据类型 相同的语法定义,并支持两个可选属性:
allowedTargets
:指定注解可以应用的目标位置类型,值为字符串或字符串数组。allowMultiple
:布尔值,表示是否允许在同一个目标位置多次使用该注解,默认为false
。
下面是一个包含多个属性和配置的注解类型示例:
annotationTypes:
complexValueType:
allowMultiple: true
properties:
prop1: integer
prop2: string
prop3: boolean
2.1. 支持注解的目标位置
注解可以应用在多个根级别的目标位置上,包括:
- API 根级别
- 资源类型(resource types)
- 特性(traits)
- 数据类型(data types)
- 文档项(documentation items)
- 安全方案(security schemes)
- 库(libraries)
- 覆盖(overlays)
- 扩展(extensions)
- 其他注解类型
此外,注解也可以用于:
- 安全方案设置(security scheme settings)
- 资源(resources)
- 方法(methods)
- 响应声明(responses)
- 请求体(request bodies)
- 响应体(response bodies)
- 命名示例(named examples)
2.2. 限制注解类型的目标位置
如果要限制某个注解类型只能用于特定的目标位置,可以设置 allowedTargets
属性。
当只允许一个目标类型时,使用字符串:
annotationTypes:
supportsOnlyOneTargetLocationType:
allowedTargets: TypeDeclaration
当允许多个目标类型时,使用数组:
annotationTypes:
supportsMultipleTargetLocationTypes:
allowedTargets: [ Library, Overlay, Extension ]
⚠️ 如果没有定义 allowedTargets
,则该注解类型默认可以用于所有支持的位置。
3. 应用注解类型
在 RAML API 规范的根级别定义好注解类型之后,就可以将它们应用到具体的目标位置,并提供相应的属性值。在目标位置中使用注解类型的行为,就称为对该目标的 注解。
3.1. 语法
应用注解类型的语法如下:
- 将注解名称用括号
()
包裹,作为目标位置的一个属性。 - 提供注解类型所需的属性值。
- 如果注解类型定义在某个 RAML 库中,使用
库名.注解名
的格式引用。
3.2. 示例
下面的示例展示了如何将前面定义的注解类型应用到 API 中的资源和方法上:
/foos:
type: myResourceTypes.collection
(simpleImplicitStringValueType): alpha
...
get:
(simpleExplicitStringValueType): beta
...
/{fooId}:
type: myResourceTypes.item
(complexValueType):
prop1: 4
prop2: testing
prop3: true
4. 实际应用场景
注解的一个典型用途是 为 API 定义和配置测试用例。
假设我们要开发一个 RAML 处理工具,可以根据注解自动生成 API 测试用例。可以定义如下的注解类型:
annotationTypes:
testCase:
allowedTargets: [ Method ]
allowMultiple: true
usage: |
使用此注解来声明一个测试用例。
每个方法上可以多次使用该注解。
properties:
scenario: string
setupScript?: string[]
testScript: string[]
expectedOutput?: string
cleanupScript?: string[]
然后在 /foos
资源的方法上配置多个测试用例:
/foos:
type: myResourceTypes.collection
get:
(testCase):
scenario: No Foos
setupScript: deleteAllFoosIfAny
testScript: getAllFoos
expectedOutput: ""
(testCase):
scenario: One Foo
setupScript: [ deleteAllFoosIfAny, addInputFoos ]
testScript: getAllFoos
expectedOutput: '[ { "id": 999, "name": Joe } ]'
cleanupScript: deleteInputFoos
(testCase):
scenario: Multiple Foos
setupScript: [ deleteAllFoosIfAny, addInputFoos ]
testScript: getAllFoos
expectedOutput: '[ { "id": 998, "name": "Bob" }, { "id": 999, "name": "Joe" } ]'
cleanupScript: deleteInputFoos
✅ 通过这种方式,我们可以将测试逻辑与 API 定义紧密集成,便于自动化工具生成测试脚本。
5. 总结
本教程展示了如何通过自定义 注解 来扩展 RAML API 规范的元数据。
我们首先介绍了如何使用 annotationTypes
声明注解类型,并列举了注解可以应用的目标位置。
接着演示了如何在 API 中使用注解,以及如何限制注解的使用范围。
最后,我们通过一个测试用例的示例,展示了注解在实际开发中的潜在用途。
📚 想了解更多关于 RAML 注解的内容,可以查阅 RAML 1.0 规范文档。
完整示例代码可在 GitHub 项目中查看:annotations 示例项目。