几乎每个做过搜索接口的后端,都写过这种端点:
1 | POST /products/search |
创建产品?没有。
为啥还用 POST?筛选条件嵌套三层,品牌数组塞几十个,价格区间再加排序和关键词。GET 的 query string 快被你写成方言了:URI 太长,编码难看,日志还把用户输入整行摊开。大家就默契地用 POST 顶着。
能跑。语义上却一直拧巴。
2026 年 6 月,IETF 把这窟窿补上了。RFC 10008 定了 HTTP 方法 QUERY:条件放 body,方法本身安全、幂等,规范层面也允许缓存。
我习惯叫它「带 body 的 GET 请求」。
GET 不够用,POST 又太重
GET 对“读”是对的。安全、幂等。缓存、代理、可观测性工具最吃这一套。
麻烦在输入塞 URI:
1 | GET /products?category=hardware&brand=a&brand=b&price.min=10&price.max=500&sort=-createdAt |
简单过滤没问题。一上嵌套对象、布尔组合、大 ID 列表、搜索 DSL,query string 就发明规矩:重复 key、逗号分隔、方括号。
POST 把 body 问题抹平了,语义却写歪了:
1 | POST /products/search |
你的 Controller 清楚:只读。网关、CDN、客户端重试策略不看你源码。它们只看见 POST。默认不当 GET 缓存,断线也不敢随便重放,生怕真改了状态。
RFC 还提了一件脏事:URI 比 body 更容易进日志、进书签。检索条件挂在 URL 上,泄露面更大。body 也不是自动隐私,只是没那么常被“整行记下来”。
缺口其实很窄:
HTTP 需要一种安全且幂等的方法,把查询输入放在请求内容里,而不是 URI 里。
QUERY 干的就是这个。不是再造一个读动词,是把复杂查询从 GET 和 POST 夹缝里拎出来。
RFC 10008: QUERY 方法
官方抽象很直白:QUERY 请求目标资源,以安全、幂等的方式处理请求体里的内容,再返回结果。
长这样:
1 | QUERY /products |
路径圈定资源范围;“怎么查”在 body 和 media type 里。
对照着看:
| GET | QUERY | POST | |
|---|---|---|---|
| 安全 | 是 | 是 | 未必 |
| 幂等 | 是 | 是 | 未必 |
| 查询输入 | URI | 请求体 | 请求体(方法语义却是“可能改状态”) |
| 默认可缓存 | 是 | 是(缓存键要算上 body) | 通常否 |
Spring Boot 如何使用
Spring Boot 4.1.0 内置的 Tomcat 解析 HTTP/1.1 时,不必先在 enum 里登记 QUERY 才能进 Servlet。请求能到应用,卡在 Spring 怎么映射。
HttpMethod 已经认 QUERY。Framework 7 里它是 final class,不是死 enum:
1 | HttpMethod.valueOf("QUERY") |
RestClient、WebClient、声明式 HTTP 客户端发 QUERY,不必干等新常量。
真正卡住的是 MVC 的 RequestMethod。注解路由还绑着:
1 | GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE |
于是这行现在编不过:
1 | // 没有 QUERY |
WebFlux 函数式路由
method 谓词吃 HttpMethod,不绑 RequestMethod enum。Boot 4.1 可以直接写:
1 | RouterFunction<ServerResponse> routes = RouterFunctions.route() |
已经在 WebFlux 的项目,改动面小,语义也干净。
自定义 MVC 桥接
注解 Controller 还得等官方扩枚举。在那之前,社区绕开 @RequestMapping(method = …),常见四块:
- 方法注解
@HttpQueryMapping(别合成@RequestMapping,否则又撞 enum) RequestCondition:运行时比"QUERY".equalsIgnoreCase(request.getMethod())- 自定义
RequestMappingHandlerMapping:扫到注解就拼 path / consumes / produces + 自定义 condition - 可选:
DispatcherServlet子类 +WebMvcRegistrations,把 QUERY 送进 Spring 分发链
业务侧会长这样:
1 |
|
收尾
截止本文发布,Spring 官方还没把 QUERY 映射到 @RequestMapping 注解里。社区已经有 PR:
预计在 spring-framework 7.1.x / Spring Boot 4.2.x 里正式支持。