当前位置:网站首页>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();
效果:
好的,这篇就到这。
边栏推荐
- flutter系列之:flutter中的flow
- Pet hospital management system based on SSMP
- CEC-I 中华学习机使用说明与问答
- About Random Numbers
- 超越锂电池——未来电池的概念
- 网上开通证券账户安全吗 手机炒股靠谱吗
- TopoLVM: 基于LVM的Kubernetes本地持久化方案,容量感知,动态创建PV,轻松使用本地磁盘
- Visual introduction to Matplotlib and plotnine
- find_ Detailed use guide of CIRC
- Moher College - SQL injection vulnerability test (error reporting and blind note)
猜你喜欢

Central Limit Theorem

C#程序结构预览最基础入门

Bootstrapblazor + FreeSQL actual combat chart usage (2)

USB协议中HID设备描述符以及键盘按键值对应编码表

Moher College -x-forwarded-for injection vulnerability practice

IIS deploy static web site and FTP service

07 | workflow design: how to design a reasonable multi person development mode?

ESP32-SOLO开发教程,解决CONFIG_FREERTOS_UNICORE问题

Law of Large Numbers

Unable to create a folder to save the sketch: MKDIR sketch
随机推荐
高清滑环生产过程当中的质量如何把控
flutter系列之:flutter中的flow
Sword finger offer 10- ii Frog jumping on steps
Custom MVC (imported into jar package) + difference from three-tier architecture + reflection + interview questions
Account management, database building and four engines + cases of MySQL
其他服务注册与发现
Great health industry annual must attend event, 2022 Shandong International Great Health Industry Expo
Kept to implement redis autofailover (redisha) 17
How to write test cases and a brief introduction to go unit test tool testify
30《MySQL 教程》MySQL 存储引擎概述
Kept to implement redis autofailover (redisha) 11
leetcode 1143. Longest Commom Subsequence 最长公共子序列(中等)
3線spi屏幕驅動方式
Gaussian and Summary Stats
气液滑环与其他滑环的工作原理有什么区别
USB协议中HID设备描述符以及键盘按键值对应编码表
XSS攻击笔记(上)
Batch generate folders based on file names
Custom class loader encrypts and decrypts classes
Memcached foundation 2