RAML中?!、<<>>、!include、get?:及resourceTypes用法咨询
嘿,我完全懂你的感受——RAML 的语法一开始看着就像一堆摸不着头脑的符号,官方文档有时候又太抽象,让人越看越懵。咱们一个个拆解这些元素,用简单直白的示例讲清楚,保证你看完就能上手。
1. !include 里的 !:引入外部文件的标记
这个 ! 是 RAML 的内置标签,专门用来告诉解析器:“我要把另一个文件里的内容直接插到这里来”。核心作用就是复用代码,避免重复写相同的配置(比如通用请求头、响应模板)。
举个实际例子:
先写一个单独的 common-headers.raml 文件,存放所有接口都要用的请求头:
headers: Authorization: description: 身份验证的Bearer Token type: string Content-Type: enum: - application/json - application/xml
然后在主 API 文件里用 !include 引入它:
#%RAML 1.0 title: 用户管理API version: v1 /users: get: !include common-headers.raml # 直接把common-headers里的内容插在这 responses: 200: body: application/json: example: | [{"id": 1, "name": "张三"}]
这样一来,所有需要这些请求头的接口,都不用重复写一遍,改的时候只需要改 common-headers.raml 就行,维护起来超方便。
2. get?: 里的 ?:标记可选的方法/资源
这个 ? 表示这个HTTP方法或者资源是可选的——意思是:这个API可能实现了这个端点,也可能没实现,客户端不能默认它一定存在。
示例1:可选的HTTP方法
#%RAML 1.0 title: 商品API version: v1 /products: get: responses: 200: description: 获取所有商品列表 get?: # 这个接口是可选的,比如某些部署环境没开筛选功能 description: 按分类筛选商品(可选功能) queryParameters: category: type: string responses: 200: description: 筛选后的商品列表
示例2:可选的资源
/products/{productId}/reviews?: # 评论资源是可选的,部分商品可能没有评论功能 get: responses: 200: description: 商品评论(如果存在的话)
这个标记主要是给API使用者看的,提醒他们要做容错处理;对开发者来说,是用来标注哪些是可选实现的功能模块。
3. <<>>:参数化引用资源类型/特质
<<>> 是用来给预定义的 resourceTypes(资源类型)或 traits(特质)传递参数的,相当于把通用模板“填充”成适合当前资源的具体配置,是RAML实现代码复用的核心手段之一。
先看和 resourceTypes 配合的完整示例:
第一步:定义参数化的资源类型
先写一个通用的集合资源模板,它接受 resourceName 参数:
#%RAML 1.0 title: 图书馆API version: v1 resourceTypes: collectionResource: description: 一组<<resourceName>>的集合 get: description: 获取所有<<resourceName>> responses: 200: description: <<resourceName>>列表 post: description: 创建新的<<resourceName>> responses: 201: description: <<resourceName>>创建成功
第二步:用 <<>> 引用并传参
把这个模板应用到具体的资源上,传入不同的 resourceName 参数:
# 应用到/books资源,传入resourceName为"图书" /books: type: <<collectionResource(resourceName: "图书")>> # 应用到/authors资源,传入resourceName为"作者" /authors: type: <<collectionResource(resourceName: "作者")>>
这样展开后,/books 的get方法描述就是“获取所有图书”,post的201响应描述是“图书创建成功”——完全不用重复写每个资源的基础CRUD逻辑,复用性拉满。
再举个和 traits(特质)配合的例子:
先定义一个带参数的分页特质:
traits: paginated: queryParameters: page: type: integer default: 1 limit: type: integer default: <<defaultLimit>> # 这里是参数占位符
然后用 <<>> 给它传参并应用到方法上:
/books: get: is: <<paginated(defaultLimit: 20)>> # 传入默认每页20条 responses: 200: description: 分页后的图书列表
这样get方法就自动拥有了 page 和 limit 参数,而且limit的默认值是20,超省心。
4. resourceTypes 完整实战示例
把上面的知识点结合起来,写一个完整的电商API示例,你就能明白这些符号怎么协同工作了:
#%RAML 1.0 title: 电商API version: v2 # 定义通用资源类型 resourceTypes: # 单个资源模板(比如/product/{id}) singleResource: description: 单个<<resourceName>>详情 get: description: 获取ID为{<<resourceId>>}的<<resourceName>> responses: 200: description: <<resourceName>>详情 404: description: <<resourceName>>不存在 # 集合资源模板 collectionResource: description: <<resourceName>>集合 get: is: <<paginated(defaultLimit: 15)>> responses: 200: description: <<resourceName>>列表 post: responses: 201: description: <<resourceName>>创建成功 # 定义分页特质 traits: paginated: queryParameters: page: type: integer minimum: 1 default: 1 limit: type: integer minimum: 5 maximum: 50 default: <<defaultLimit>> # 引入通用请求头 !include common-headers.raml # 应用资源类型和特质 /products: type: <<collectionResource(resourceName: "商品")>> /{productId}: type: <<singleResource(resourceName: "商品", resourceId: "productId")>> # 可选的删除方法,部分部署环境不支持删除商品 delete?: description: 删除商品(可选功能) responses: 204: description: 商品已删除
这样一套下来,整个API的结构清晰,重复代码极少,维护起来也方便很多。
内容的提问来源于stack exchange,提问作者Prasad

