如何解决getReader() has already been called for this request问题
作者:终遇你..
这篇文章主要介绍了如何解决getReader() has already been called for this request问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
解决getReader() has already been called for this request
在 Filter 中对 request 中的 body 进行参数签名校验
会报如下错误:
getReader() has already been called for this request
原因是
request.getReader() 和 request.getInputStream() 都是只能调用一次
并且 getReader() 方法底层也是调用 getInputStream() 来实现的.
所以我们要使用 HttpServletRequestWrapper 来实现自定义的 CustomHttpServletRequestWrapper, 把 body 保存在 CustomHttpServletRequestWrapper 中, 并且重写 getInputStream() 方法
重写 HttpServletRequestWrapper
package com.fosung.pb.village.config;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class MyRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public MyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
if(ServletFileUpload.isMultipartContent(request)){
return;
}
StringBuilder sb = new StringBuilder();
String line;
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String body = sb.toString();
this.body = body.getBytes(StandardCharsets.UTF_8);
}
public String getBody() {
return new String(this.body , StandardCharsets.UTF_8) ;
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = 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 bais.read();
}
};
}
@Override
public BufferedReader getReader(){
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}Filter 使用
package com.fosung.pb.village.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lanx
* @date 2022/4/11
*/
@Slf4j
@Component
@WebFilter(filterName = "AntiSqlInjectionfilter", urlPatterns = "/*")
public class AntiSqlInjectionfilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
MyRequestWrapper myRequestWrapper = null;
// 获取请求body
try {
myRequestWrapper = new MyRequestWrapper(req);
} catch (IOException e) {
log.error("get request body exception", e);
throw new RuntimeException(e);
}
if ("POST".equalsIgnoreCase(req.getMethod())) {
String param = myRequestWrapper.getBody();
chain.doFilter(myRequestWrapper, response);
} else {
chain.doFilter(myRequestWrapper, response);
}
}
}总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
- 解决异常处理问题:getReader() has already been called for this
- 解决java启动时报线程占用报错:Exception in thread “Thread-14“ java.net.BindException: Address already in use: bind
- 如何解决Mybatis--java.lang.IllegalArgumentException: Result Maps collection already contains value for X
- SVN出现提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir解决方案
- 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法
