如何解決getReader() has already been called for this request問題
解決getReader() has already been called for this request
在 Filter 中對 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() 來實(shí)現(xiàn)的.
所以我們要使用 HttpServletRequestWrapper 來實(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; // 獲取請求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è)參考,也希望大家多多支持腳本之家。
- 解決異常處理問題: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實(shí)現(xiàn)簡單搭建內(nèi)網(wǎng)穿透
內(nèi)網(wǎng)穿透是一種網(wǎng)絡(luò)技術(shù),適用于需要遠(yuǎn)程訪問本地部署服務(wù)的場景,本文主要為大家介紹了如何使用Java實(shí)現(xiàn)簡單搭建內(nèi)網(wǎng)穿透,感興趣的可以了解下2024-02-02ReentrantReadWriteLock不能鎖升級的原因總結(jié)
今天給大家?guī)淼氖顷P(guān)于Java并發(fā)的相關(guān)知識,文章圍繞著為什么ReentrantReadWriteLock不能鎖升級展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06Spring?@EventListener?異步中使用condition的問題及處理
這篇文章主要介紹了Spring?@EventListener?異步中使用condition的問題及處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn)代碼
這篇文章主要介紹了IDEA中WebService生成Java代碼并調(diào)用外部接口實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05java實(shí)現(xiàn)發(fā)送郵件的示例代碼
這篇文章主要介紹了java如何實(shí)現(xiàn)發(fā)送郵件,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07基于SpringBoot+Avue實(shí)現(xiàn)短信通知功能
Avue是基于vue和element-ui的快速開發(fā)框架 ,它的核心是數(shù)據(jù)驅(qū)動(dòng)UI的思想,讓我們從繁瑣的crud開發(fā)中解脫出來,本文將給大家介紹一下使用SpringBoot+Avue實(shí)現(xiàn)短信通知功能,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-09-09詳解使用Spring3 實(shí)現(xiàn)用戶登錄以及權(quán)限認(rèn)證
這篇文章主要介紹了詳解使用Spring3 實(shí)現(xiàn)用戶登錄以及權(quán)限認(rèn)證,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2017-03-03