成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

實戰揭秘!Spring Boot 3.4 多 @RequestBody 處理技巧,輕松應對復雜入參

開發 前端
在實際開發中,你可以根據項目需求選擇合適的方案,從而更高效地處理復雜的 JSON 請求體解析。希望本指南能幫助你輕松應對 Spring Boot 3.4 的多 @RequestBody 解析問題!?

在 Spring Boot 3.4 開發過程中,@RequestBody 注解是解析 HTTP 請求體 JSON 數據的常見方式,能夠自動將數據綁定到 Java 對象中。然而,當 API 需要同時接收多個對象時,直接使用多個 @RequestBody 會導致 HttpMessageNotReadableException 異常。究其原因,這是由于 HttpServletRequest 的輸入流只能被讀取一次,第二個 @RequestBody 無法再次獲取數據。

本文將深入剖析這一問題的本質,并提供兩種不同的解決方案:

  1. 使用 DTO 進行封裝(適用于前端可以調整數據格式的場景)。
  2. 自定義 HttpServletRequestWrapper(適用于無法修改前端請求結構的情況)。

通過這些方法,你可以在 Spring Boot 3.4 項目中靈活應對復雜的 JSON 請求體解析問題。

解決方案

方法 1:使用 DTO 進行封裝

我們可以創建一個 RequestDTO 類,將 User 和 Person 統一封裝。

package com.icoderoad.dto;

public class RequestDTO {
    private User user;
    private Person person;
    // getter 和 setter
}

然后修改 Controller 方法:

package com.icoderoad.controller;


import com.icoderoad.dto.RequestDTO;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/api")
public class MultiRequestBodyController {
    @PostMapping("/multi")
    public String handleMultiple(@RequestBody RequestDTO dto) {
        return "Received: " + dto.getUser().getName() + " and " + dto.getPerson().getName();
    }
}

這種方式雖然簡單,但要求前端調整 JSON 數據格式。

方法 2:自定義 HttpServletRequestWrapper 允許多次讀取請求體

如果前端無法調整請求格式,我們可以使用 HttpServletRequestWrapper 解決 InputStream只能讀取一次的問題。

自定義 CachedBodyHttpServletRequest

package com.icoderoad.wrapper;


import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StreamUtils;


import java.io.*;


public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
    private final byte[] cachedBody;


    public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        InputStream requestInputStream = request.getInputStream();
        this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
    }


    @Override
    public ServletInputStream getInputStream() {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cachedBody);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener listener) {}
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }
        };
    }
}

創建過濾器攔截請求

package com.icoderoad.filter;


import com.icoderoad.wrapper.CachedBodyHttpServletRequest;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;


import java.io.IOException;


@Component
public class CachedBodyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {
            CachedBodyHttpServletRequest wrappedRequest = new CachedBodyHttpServletRequest((HttpServletRequest) request);
            chain.doFilter(wrappedRequest, response);
        } else {
            chain.doFilter(request, response);
        }
    }
}

配置過濾器

package com.icoderoad.config;


import com.icoderoad.filter.CachedBodyFilter;
import jakarta.servlet.Filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


import java.util.List;


@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<Filter> cachedBodyFilter() {
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new CachedBodyFilter());
        registrationBean.setUrlPatterns(List.of("/*"));
        return registrationBean;
    }
}

結論

在 Spring Boot 3.4 版本中,同時解析多個 @RequestBody 參數是一項常見但容易踩坑的挑戰。本文提供了兩種解決方案:

  • DTO 封裝方式適用于可以修改前端請求格式的場景,簡單易用,但需要前端配合調整 JSON 結構。
  • HttpServletRequestWrapper 方案適用于無法修改前端數據格式的情況,能夠確保多個 @RequestBody 參數的正常解析。

在實際開發中,你可以根據項目需求選擇合適的方案,從而更高效地處理復雜的 JSON 請求體解析。希望本指南能幫助你輕松應對 Spring Boot 3.4 的多 @RequestBody 解析問題!

責任編輯:武曉燕 來源: 路條編程
相關推薦

2025-04-27 04:00:00

錯誤頁Spring底層

2025-03-31 01:22:00

2020-04-23 15:59:04

SpringKafka集群

2025-05-12 08:00:00

Expect腳本自動化運維

2023-10-23 09:44:00

并發管理線程

2025-03-27 08:10:19

Spring開發架構

2024-07-03 08:49:32

2025-02-17 00:00:45

接口支付寶沙箱

2024-01-31 08:50:41

Guava并發工具

2023-04-11 16:04:19

Spring Boo端點運維

2024-02-01 18:06:04

Python編程系統

2025-01-07 08:21:03

2023-09-24 13:55:42

Spring應用程序

2024-12-03 10:46:48

Spring優化開發

2025-01-13 12:46:31

SpringBootJacksonJSON

2025-02-21 16:00:00

SpringBoot代碼開發

2025-04-03 07:56:08

電子簽名合同系統Spring

2025-01-15 12:43:23

2025-05-13 07:13:25

2024-08-09 08:52:26

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 毛片一区二区 | 在线超碰 | 操久久| 国产精品爱久久久久久久 | 国产亚洲精品精品国产亚洲综合 | 成人免费视频网站在线看 | 国产在线不卡 | 久久久成人免费视频 | 99婷婷| 日韩成人精品视频 | 国产精品99999| 婷婷丁香综合网 | 日日摸夜夜添夜夜添精品视频 | 亚洲高清免费 | 亚洲高清久久 | 中文字幕一级毛片 | 国产专区在线 | 日日摸夜夜添夜夜添精品视频 | 国产精品视频播放 | 中文字幕视频在线观看免费 | 精品av天堂毛片久久久借种 | 99re视频在线免费观看 | 色888www视频在线观看 | 亚洲啊v在线| 日本精品视频在线 | 国产精品久久久久久久久动漫 | 91免费在线 | 久久成人18免费网站 | 国内精品视频 | 日韩色视频 | 久久成人精品 | 国产99久久精品一区二区永久免费 | 91看国产| 狠狠躁夜夜躁人人爽天天高潮 | 亚洲视频在线免费观看 | 亚洲一区二区三区四区五区午夜 | 免费国产视频在线观看 | 久久久高清 | 国产农村妇女毛片精品久久麻豆 | 国产一区不卡 | 精品国产一区二区三区久久 |