Spring Boot 条件分页查询接口:从 GET + @RequestBody 踩坑到 POST 解决方案

在最近做“原材料入库管理”模块时,我遇到了一个常见的坑:在 GET 请求里用 @RequestBody 接收 JSON 条件参数。这里记录一下踩坑→分析→解决的过程,供大家参考。


背景:想用 GET + @RequestBody 做条件查询

起初我写的 Controller:

/**
 * 查询原材料入库记录列表(支持分页)
 */
@ApiOperation("查询原材料入库记录列表")
@PreAuthorize("@ss.hasPermi('datamanager:rawMaterialReceipt:list')")
@GetMapping("/list")
public TableDataInfo list(DtsFactoryRawMaterialReceiptQuery query) {
    startPage();
    List<DtsFactoryRawMaterialReceiptVO> list = receiptService.selectList(query);
    return getDataTable(list);
}

前端打算用 JSON body 把查询条件传过来。

结果运行时参数接受不到:


原因分析:HTTP GET 与 @RequestBody 不兼容

  • HTTP 语义:GET 用于“获取资源”,标准里没有定义 GET 请求 body 的语义。
  • 框架行为:Spring MVC 遵循这个惯例,默认不会解析 GET 请求的 body,@RequestBody 接收不到值。

所以在 GET 接口里直接用 @RequestBody 是无效的。


两种可行的改法

方案 A:保持 GET,用 QueryParam 传参

去掉 @RequestBody,Spring 会自动把 URL 查询参数绑定到 DTO:

@GetMapping("/list")
public TableDataInfo list(DtsFactoryRawMaterialReceiptQuery query) {
    startPage();
    List<DtsFactoryRawMaterialReceiptVO> list = receiptService.selectList(query);
    return getDataTable(list);
}

前端调用示例:

GET /datamanager/factoryRawMaterialReceipt/list?factoryId=1&supplierId=2&inStockStartTime=2025-09-01%2000:00:00

这种方式适合条件比较少、可以用查询字符串表达的场景。

方案 B:改成 POST,用 JSON body 传参(我最终采用的方案)

如果条件很多或需要嵌套 JSON,改成 POST 接口:

/**
 * 条件分页查询原材料入库记录列表(支持分页)
 */
@ApiOperation("条件分页查询原材料入库记录列表")
@PreAuthorize("@ss.hasPermi('datamanager:rawMaterialReceipt:list')")
@PostMapping("/list")
public TableDataInfo list(@RequestBody DtsFactoryRawMaterialReceiptQuery query) {
    startPage();
    List<DtsFactoryRawMaterialReceiptVO> list = receiptService.selectList(query);
    return getDataTable(list);
}

前端调用示例:

POST /datamanager/factoryRawMaterialReceipt/list
Content-Type: application/json

{
  "pageNum":2,
  "pageSize":10,
  "inStockStartTime": "2025-09-01 00:00:00",
  "inStockEndTime": "2025-09-30 23:59:59"
}

Spring 会把 JSON 自动反序列化到 query 对象。

一个新问题

此时又有了一个新问题,分页失效了,怎么插都是第一页,就是因为使用了post,将分页的两个参数也放在了请求体的JSON里,而StartPage规定这两个参数是在url里作为request parameter读取的。所以这里就需要手动从query对象里取出这两个值手动设置分页查询:

/**
     * 条件分页查询原材料入库记录列表(支持分页)
     */
    @ApiOperation("条件分页查询原材料入库记录列表")
    @PreAuthorize("@ss.hasPermi('datamanager:rawMaterialReceipt:list')")
    @PostMapping("/list")
    public TableDataInfo list(@RequestBody DtsFactoryRawMaterialReceiptQuery query) {
        // 手动启动分页
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<DtsFactoryRawMaterialReceiptVO> list = receiptService.selectList(query);
        return getDataTable(list);
    }

注:query:

@Data
public class DtsFactoryRawMaterialReceiptQuery {
    private Integer pageNum;
    private Integer pageSize;
    private Long factoryId;
    private Long supplierId;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime inStockStartTime; // 入库开始时间
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime inStockEndTime;   // 入库结束时间
}

有一个新问题

前端某个页面初始化时要调用两次这个接口(条件不同),但是前端又做了全局的post防抖(1S内不能连续请求两次post)。

这里暂时在前端用白名单的方式处理,但不优雅。。。所以之后我还是先按get方法写吧…

简单总结一下:

🔎 问题根源

  1. 接口语义不对
    • 条件查询本质是“读取数据”,按 HTTP/REST 语义应该用 GET;
    • 用 POST 只是因为要传 JSON,但违背了原本的语义,导致和前端全局策略冲突。
  2. 前端防抖策略过粗
    • 前端把所有 POST 一刀切防抖,缺乏按“接口 + 参数”维度的精细化控制;
    • 导致即便是两个不同条件的查询也被拦掉。
  3. 幂等性不是这个问题的解法
    • 幂等性能保证“相同请求多次执行结果一致”,不能替代防抖、也不能合并不同条件的请求。

✅ 最佳实践

场景HTTP 方法后端处理前端处理
条件查询/分页GET(推荐)DTO 接收 QueryParam;天然幂等可按需防抖(输入搜索时),不一刀切
写操作(新增、下单、扣款)POST/PUT/DELETE必须做幂等性(防重复提交)可以防抖以减少用户误触
复杂查询条件 JSONPOST /search(仅为传参方便)标注清楚语义仍是查询精细化防抖(按 URL+参数 key)
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇