0

0

RESTful API 设计:路径参数与请求体对象的职责分离最佳实践

霞舞

霞舞

发布时间:2026-02-09 10:52:20

|

703人浏览过

|

来源于php中文网

原创

RESTful API 设计:路径参数与请求体对象的职责分离最佳实践

restful api 设计中,应严格区分资源标识(由 @pathvariable 承载)与资源状态变更数据(由 @requestbody 承载);将路径参数强行注入请求体 dto 不仅违背 rest 原则,还破坏数据契约清晰性、可测试性与序列化一致性。

✅ 正确的设计原则:路径即资源定位,请求体即资源状态

REST 的核心思想是 “URL 表示资源,HTTP 方法表示操作”。你定义的端点:

POST /v1/myapi/bank/{bank_id}/branch/{branch_id}

从语义上已明确指向「在指定银行下创建/操作某一分支机构」——此时 {bank_id} 和 {branch_id} 是资源的唯一标识符(URI path components),而非业务数据的一部分。而 BankDetails 作为 @RequestBody,其职责应仅描述该分支的可变属性(如 address、zip),不应对标识字段进行冗余建模。

将 bankId 和 branchId 加入 BankDetails 类,并用 @JsonProperty(access = JsonProperty.Access.READ_ONLY) 掩盖其不可反序列化的问题,本质上是一种契约污染

  • 前端调用时无法通过 OpenAPI/Swagger 准确感知哪些字段由路径提供、哪些由 JSON 提供;
  • 序列化/反序列化逻辑耦合路径处理逻辑,导致 BankDetails 在非 Web 层(如消息队列消费端)使用时需额外补全 ID 字段,破坏 POJO 的纯净性;
  • READ_ONLY 仅影响 Jackson 反序列化,但若未来启用其他序列化器(如 Protobuf、JSON-B),行为不可控。

✅ 推荐方案:保持 DTO 纯净,组合构建领域对象

在控制器中,应将路径参数与请求体解耦处理,再在服务层或 DTO 转换层显式组合:

@PostMapping(value = "/v1/myapi/bank/{bank_id}/branch/{branch_id}", 
               produces = "application/json")
public ResponseEntity createBankBranch(
    @PathVariable("bank_id") String bankId,
    @PathVariable("branch_id") String branchId,
    @RequestBody BankDetails details) {

    // ✅ 构建完整上下文对象(非修改原始 DTO)
    BranchCreationCommand command = BranchCreationCommand.builder()
        .bankId(bankId)
        .branchId(branchId)
        .address(details.getAddress())
        .zip(details.getZip())
        .build();

    // 发送至 SQS 队列(如封装为 JSON 消息)
    sqsService.sendMessage(command);

    return ResponseEntity.ok(new MyResponse("queued"));
}

对应的消息载体类(专用于队列传输,非 API 入参 DTO):

OmniAudio
OmniAudio

OmniAudio 是一款通过 AI 支持将网页、Word 文档、Gmail 内容、文本片段、视频音频文件都转换为音频播客,并生成可在常见 Podcast ap

下载
// BranchCreationCommand.java —— 面向消息场景的专用 DTO
public class BranchCreationCommand {
    private String bankId;
    private String branchId;
    private String address;
    private String zip;

    // Lombok @Builder + @Data recommended
}
? 关键优势: BankDetails 保持纯数据传输对象(DTO),仅含业务属性,无 URI 偶然性字段; BranchCreationCommand 是面向领域/消息的命令对象,天然包含上下文 ID; 控制器职责清晰:解析请求 → 映射上下文 → 构建命令 → 分发; 消费端(如 SQS Worker)直接反序列化 BranchCreationCommand,无需任何额外字段填充或空值校验。

⚠️ 补充说明:关于你的 URL 设计是否合理?

正如答案中指出:POST /bank/{bank_id}/branch/{branch_id} 更符合 “更新/操作已知分支” 的语义(例如 PUT 修改分支信息)。若目标是「创建新分支」,更 RESTful 的设计应为:

POST /v1/myapi/bank/{bank_id}/branches   ← 集合资源,返回 201 + Location

其中 branch_id 由服务端生成(或由客户端提供并校验唯一性),路径中不预先暴露待创建资源的 ID。这既符合 HATEOAS 原则,也避免了 POST 与 PUT 语义混淆。

✅ 总结

项目 不推荐做法 推荐做法
DTO 职责 在 @RequestBody DTO 中混入 @PathVariable 字段 DTO 仅承载可变业务属性;ID 由路径/查询参数独立提供
序列化契约 用 READ_ONLY 掩盖字段不可反序列化问题 使用专用命令对象(Command DTO),明确用途与结构
解耦性 控制器直接修改传入 DTO 控制器构造新对象,保持入参不可变(函数式风格)
可维护性 同一类在不同场景承担多重语义 按关注点分离:API DTO、Command DTO、Domain Entity

遵循此模式,你的 API 将更健壮、可演进,并自然支持异步化、事件驱动等现代架构模式。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
PHP API接口开发与RESTful实践
PHP API接口开发与RESTful实践

本专题聚焦 PHP在API接口开发中的应用,系统讲解 RESTful 架构设计原则、路由处理、请求参数解析、JSON数据返回、身份验证(Token/JWT)、跨域处理以及接口调试与异常处理。通过实战案例(如用户管理系统、商品信息接口服务),帮助开发者掌握 PHP构建高效、可维护的RESTful API服务能力。

170

2025.11.26

json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

433

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

543

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

315

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

79

2025.09.10

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

189

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

294

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

264

2025.06.11

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

98

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.4万人学习

C# 教程
C# 教程

共94课时 | 9万人学习

Java 教程
Java 教程

共578课时 | 61.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号