当前位置:网站首页>getReader() has already been called for this request
getReader() has already been called for this request
2022-06-27 00:34:00 【小目标青年】
问题现场:

原因:
HttpServletRequest 的 getInputStream() 和 getReader() 都只能读取一次。
因为 我们使用@RequestBody 注解,读取body参数;而 又 写了拦截器,也需要将post请求,body数据拿出来。
由于@RequestBody 也是流的形式读取,流读了一次就没有了。
解决方案:
过滤器是优先于拦截器的, 我们写一个过滤器,在过滤器里面 把流数据 copy一份出来用,也就是复写一哈。
在拦截器上使用我们复写的流数据就行。
BodyWrapperFilter.java
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @Author: JCccc
* @Date: 2022-6-12 10:35
* @Description:
*/
public class BodyWrapperFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(servletRequest instanceof HttpServletRequest) {
requestWrapper = new CustomHttpServletRequestWrapper((HttpServletRequest) servletRequest);
}
if(requestWrapper == null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
}CustomHttpServletRequestWrapper.java
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* @Author: JCccc
* @Date: 2022-6-12 10:36
* @Description: 重写一个自己的 RequestWrapper 拿出body给自己用
*/
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public CustomHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
BufferedReader reader = request.getReader();
try (StringWriter writer = new StringWriter()) {
int read;
char[] buf = new char[1024 * 8];
while ((read = reader.read(buf)) != -1) {
writer.write(buf, 0, read);
}
this.body = writer.getBuffer().toString().getBytes();
}
}
public String getBody(){
return new String(body, StandardCharsets.UTF_8);
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
WebApplicationConfig.java
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author: JCccc
* @Date: 2022-6-23 10:52
* @Description:
*/
@Configuration
public class WebApplicationConfig {
@Bean
BodyWrapperFilter getBodyWrapperFilter(){
return new BodyWrapperFilter();
}
@Bean("bodyWrapperFilter")
public FilterRegistrationBean<BodyWrapperFilter> checkUserFilter(BodyWrapperFilter bodyWrapperFilter) {
FilterRegistrationBean<BodyWrapperFilter> registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(bodyWrapperFilter);
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
registrationBean.setAsyncSupported(true);
return registrationBean;
}
}然后就是在拦截器里面,如果我们想取出body,我们改成这样用:
CustomHttpServletRequestWrapper wrapper = (CustomHttpServletRequestWrapper) request; String nowParams = wrapper.getBody();
效果:
好的,这篇就到这。
边栏推荐
- find_ Detailed use guide of CIRC
- Kept to implement redis autofailover (redisha) 15
- Custom jsp[if, foreach, data, select] tag
- Moher College -x-forwarded-for injection vulnerability practice
- 世界很大,有人把二维码纹在脖子上
- Great vernacular with high concurrency (I)
- 超越锂电池——未来电池的概念
- Lwip之定时机制
- Gaussian and Summary Stats
- Employment prospect of GIS and remote sensing specialty and ranking selection of universities in 2022
猜你喜欢

The most difficult 618 in history, TCL won the first place in both jd.com and tmall.com shares in the TV industry

Sword finger offer 10- ii Frog jumping on steps

One click acceleration of Sony camera SD card file copy operation, file operation batch processing tutorial

Flink 实战问题(七):No Watermark(Watermarks are only available EventTime is used)

疫情期间居家办公的总结体会 |社区征文

buuctf-pwn write-ups (6)

滑环选型选购时需要注意的技巧

Moher College - SQL injection vulnerability test (error reporting and blind note)

用代码生成流程图,Markdown的使用方法

解决unable to create a folder to save the sketch: mkdir sketch
随机推荐
Solve the problem that stc8g1k08 program cannot run and port configuration
Employment prospect of GIS and remote sensing specialty and ranking selection of universities in 2022
XML learning notes
Summary of working at home during the epidemic | community essay solicitation
Operating instructions and Q & A of cec-i China learning machine
Kept to implement redis autofailover (redisha) 12
Is it safe to open a securities account online? Is it reliable to speculate in stocks by mobile phone
Keepalived 实现 Redis AutoFailover (RedisHA)11
The world is very big. Some people tattoo QR codes on their necks
memcached基础2
How to measure the thickness of glass substrate by spectral confocal
What are the skills and methods for slip ring installation
The most difficult 618 in history, TCL won the first place in both jd.com and tmall.com shares in the TV industry
Lwip之定时机制
ESP32-SOLO开发教程,解决CONFIG_FREERTOS_UNICORE问题
Implementation of ARP module in LwIP
memcached基础5
解决STC8G1K08程序不能运行的问题和端口配置
Keepalived 实现 Redis AutoFailover (RedisHA)12
自定义JSP[if,foreach,数据,select]标签