HAL与HAL-FORMS疑问:为何将动作置于_templates而非_links
关于HAL Links vs HAL-FORMS Templates的选择与最优实践
先明确核心差异:HAL的_links和HAL-FORMS的_templates从设计初衷上就有明确的职责划分,这也是后者不把操作整合进前者的原因:
1. HAL原生_links的定位局限
HAL的_links核心是描述资源间的关联关系,比如self指向资源本身、next指向下一页、author关联创建者资源——它的作用是告诉客户端“这个资源和哪些其他资源有关、在哪里能找到它们”。虽然你可以手动给_links加method字段解决当下的操作复用问题,但这属于自定义扩展,破坏了HAL的标准规范:
- 标准HAL客户端(比如通用API工具、第三方SDK)不会识别这个自定义字段,兼容性差;
_links里混进操作元数据后,会让资源关联的语义变得模糊,响应结构可读性下降。
2. HAL-FORMS_templates的设计逻辑
HAL-FORMS是HAL的官方扩展,专门用来定义可执行的交互操作(比如创建、更新、删除资源)。它把操作放在_templates里,是因为这类操作需要的远不止URI和HTTP方法:
- 可能需要定义请求体的字段结构、数据类型、校验规则;
- 可能包含查询参数、表单参数的默认值、可选性;
- 还能标注操作的语义(比如
rel="create"明确这是创建操作)。
把这些元数据单独放在_templates里,既能和_links的资源关联职责做清晰分离,又能给前端提供足够的信息来自动处理请求(比如自动生成表单、填充默认值、校验输入),完全符合HATEOAS“链接驱动工作流”的核心思想。
3. 最优实践建议
根据你的场景,推荐以下两种方案:
方案一:纯HAL场景(简单操作)
如果你的API操作都是简单的GET/PUT/DELETE,不需要复杂的请求元数据,不要自定义_links字段,而是用标准rel语义+HTTP方法约定:
- 比如
rel="update"的链接默认对应PUT方法,rel="delete"对应DELETE; - 用Spring HATEOAS的
Link类时,通过withRel()指定标准rel,前端根据rel约定来推断HTTP方法,避免自定义扩展带来的兼容性问题。
方案二:HAL-FORMS扩展(复杂操作)
如果需要支持带请求体、参数校验的复杂操作,直接用HAL-FORMS:
- Spring HATEOAS提供了
HalFormsTemplate、HalFormsProperty等类,可以轻松生成包含操作元数据的_templates字段; - 前端可以直接解析
_templates里的信息,自动生成请求逻辑,完全不需要硬编码URI和HTTP方法,实现真正的链接驱动工作流。
兼容方案
如果要同时支持标准HAL客户端和HAL-FORMS客户端,在响应中同时保留_links(处理资源关联)和_templates(处理交互操作),各司其职,既保证规范兼容性,又给前端提供足够的操作元数据。
内容的提问来源于stack exchange,提问作者Burckhardt Sébastien
相关产品推荐
相关产品推荐

