当前位置:网站首页>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();
效果:
好的,这篇就到这。
边栏推荐
- Play OLED, u8g2 animation, increasing numbers, random triangles, etc
- buuctf-pwn write-ups (6)
- Timing mechanism of LwIP
- TopoLVM: 基于LVM的Kubernetes本地持久化方案,容量感知,动态创建PV,轻松使用本地磁盘
- Keepalived 实现 Redis AutoFailover (RedisHA)14
- memcached基础6
- memcached基础3
- 3線spi屏幕驅動方式
- Solve the problem that stc8g1k08 program cannot run and port configuration
- [vscade] preview MD file
猜你喜欢
气液滑环与其他滑环的工作原理有什么区别
Count the logarithm of points that cannot reach each other in an undirected graph [classic adjacency table building +dfs Statistics - > query set optimization] [query set manual / write details]
Solve the problem that stc8g1k08 program cannot run and port configuration
解决STC8G1K08程序不能运行的问题和端口配置
BootstrapBlazor + FreeSql实战 Chart 图表使用(2)
Esp32 experiment - self built web server distribution network 02
Moher College - SQL injection vulnerability test (error reporting and blind note)
Operating instructions and Q & A of cec-i China learning machine
用代码生成流程图,Markdown的使用方法
Implementation of ARP module in LwIP
随机推荐
Employment prospect of GIS and remote sensing specialty and ranking selection of universities in 2022
The [MySQL] time field is set to the current time by default
Other service registration and discovery
寻找旋转排序数组中的最小值 II[经典抽象二分 + 如何破局左中右三者相等]
leetcode 1143. Longest common subsequence (medium)
温故知新--常温常新
3-wire SPI screen driving mode
Lambda表达式
Law of Large Numbers
JSON解析,ESP32轻松获取时间气温和天气
Skills needing attention in selection and purchase of slip ring
How to use ch423? Cheap domestic IO expansion chip
How to convert an old keyboard into a USB keyboard and program it yourself?
自定义JSP[if,foreach,数据,select]标签
Statistical Hypothesis Testing
Gaussian and Summary Stats
How to measure the thickness of glass substrate by spectral confocal
What is the difference between the working principle of gas-liquid slip ring and other slip rings
05 | standard design (Part 2): how to standardize the different styles of commit information, which are difficult to read?
Great health industry annual must attend event, 2022 Shandong International Great Health Industry Expo