【Exception】getReader() has already been called for this request

在SpringMVC中,如果尝试多次调用HttpServletRequest的getInputStream()或getReader(),会抛出异常。解决方案是创建一个自定义的HttpServletRequestWrapper,重写getInputStream和getReader方法,保存原始请求的输入流。通过过滤器RequestBodyFilter在请求进入控制器之前,将原始请求包装成自定义包装类,从而可以多次读取请求内容。这种方式避免了异常,确保了请求流的正常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【Exception】getReader() has already been called for this request

 

一、问题描述

1、在SpringMVC的拦截器中,使用了一次 HttpServletRequest 的 getInputStream() 或 getReader() 的方法后,再次在调用,就会抛出异常:

getReader() has already been called for this request

2、最简单的触发:

    @RequestMapping(value = "/rankData/mapForm")
	@ResponseBody
	public ResultVO mapForm(HttpServletRequest request) {
		try {
			BufferedReader reader = request.getReader();
			String line ; 
			StringBuffer sb = new StringBuffer();
			while((line=  reader.readLine())!= null) {
				sb.append(line);
			}
			System.out.println("resFrom :" + sb.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			ServletInputStream inputStream = request.getInputStream();
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,Charset.defaultCharset()));
			String line ; 
			StringBuffer sb = new StringBuffer();
			while((line=  bufferedReader.readLine())!= null) {
				sb.append(line);
			}
			System.out.println("resFrom222 :" + sb.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return ResultVO.success("");
	}

 

二、解决思路

1、创建MyHttpServletRequestWrapper 类,继承 HttpServletRequestWrapper,重写 getInputStream 和 getReader 方法

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.springframework.util.StreamUtils;

/**
 * description: 重写 MyHttpServletRequestWrapper
 * @version v1.0
 * @author w
 * @date 2021年4月20日下午3:56:53
 **/

public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {

	private byte[] requestBody = null;// 用于将流保存下来

	public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
		super(request);
		requestBody = StreamUtils.copyToByteArray(request.getInputStream());
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		// 读取 requestBody 中的数据
		final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);

		return new ServletInputStream() {
			@Override
			public int read() throws IOException {
				return byteArrayInputStream.read();
			}
		};
	}

	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(getInputStream()));
	}

	/**
	 * description: 提供获取requestBody的方法
	 * 
	 * @return byte[]
	 * @version v1.0
	 * @author w
	 * @date 2021年4月20日 下午4:02:29
	 */
	public byte[] getRequestBody() {
		return requestBody;
	}
}

 

2、创建拦截器:实现对 HttpServletRequestWrapper类的重写


import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * description: RequestBodyFilter
 * @version v1.0
 * @author w
 * @date 2021年4月20日下午4:03:09
 **/
public class RequestBodyFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println(RequestBodyFilter.class.getName() + " ---->run");
		ServletRequest requestWrapper = null;
		if (request instanceof HttpServletRequest) {
			requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);
		}
		if (requestWrapper == null) {
			chain.doFilter(request, response);
		} else {
			chain.doFilter(requestWrapper, response);
		}
	}

	@Override
	public void destroy() {
		
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		
	}
}

3、配置过滤器,略。

 

三、总结

1、经过测试,分别调用: request.getReader() request.getInputStream() 方法多次,没有遇到异常信息。

2、遇到 request.getInputStream() 只能调用一次的问题,咋办呢? 重写一个HttpServletRequestWrapper 方法, 增加过滤器进行配置,即可。

 

 

参考资料: Spring Boot 添加过滤器

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值