如何解決getReader() has already been called for this request問(wèn)題
解決getReader() has already been called for this request
在 Filter 中對(duì) request 中的 body 進(jìn)行參數(shù)簽名校驗(yàn)
會(huì)報(bào)如下錯(cuò)誤:
getReader() has already been called for this request
原因是
request.getReader() 和 request.getInputStream() 都是只能調(diào)用一次
并且 getReader() 方法底層也是調(diào)用 getInputStream() 來(lái)實(shí)現(xiàn)的.
所以我們要使用 HttpServletRequestWrapper 來(lái)實(shí)現(xiàn)自定義的 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;
// 獲取請(qǐng)求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);
}
}
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 解決異常處理問(wèn)題:getReader()?has?already?been?called?for?this
- 解決java啟動(dòng)時(shí)報(bào)線程占用報(bào)錯(cuò):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出現(xiàn)提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir解決方案
- 啟動(dòng)tomcat時(shí) 錯(cuò)誤: 代理拋出異常 : java.rmi.server.ExportException: Port already in use: 1099的解決辦法
相關(guān)文章
Java Spring數(shù)據(jù)單元配置過(guò)程解析
這篇文章主要介紹了Java Spring數(shù)據(jù)單元配置過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
Java請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向區(qū)別詳解
這篇文章主要介紹了Java請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向區(qū)別詳解,請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向,但二者是完全不同的,所以我們今天就來(lái)盤他們的區(qū)別介紹,需要的朋友可以參考一下2022-07-07
SpringBoot集成RocketMQ發(fā)送事務(wù)消息的原理解析
RocketMQ 的事務(wù)消息提供類似 X/Open XA 的分布事務(wù)功能,通過(guò)事務(wù)消息能達(dá)到分布式事務(wù)的最終一致,這篇文章主要介紹了SpringBoot集成RocketMQ發(fā)送事務(wù)消息,需要的朋友可以參考下2022-06-06
Java 異步線程監(jiān)聽(tīng)與結(jié)果回調(diào)及異常捕獲總結(jié)分析
異常是程序之中導(dǎo)致程序中斷的一種指令流,異常一旦出現(xiàn)并且沒(méi)有進(jìn)行合理處理的話,那么程序就將中斷執(zhí)行,這篇文章綜合介紹了異步線程監(jiān)聽(tīng)與結(jié)果回調(diào)及異常捕獲2021-11-11
詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法
本篇文章主要介紹了詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03

