解決異常處理問題:getReader()?has?already?been?called?for?this
場景描述
在 Spring Boot 自定義攔截器中,需要對請求 body 中的內(nèi)容做簽名驗(yàn)證。
在日志切面中,需要打印請求 body 中的內(nèi)容。
報(bào)錯(cuò)內(nèi)容
java.lang.IllegalStateException: getReader() has already been called for this request
at org.apache.catalina.connector.Request.getInputStream(Request.java:1069)
at org.apache.catalina.connector.RequestFacade.getInputStream(RequestFacade.java:365)
at com.igg.aggregate.server.aspect.LogAspect.before(LogAspect.java:80)
原因分析
HttpServletRequest 的 getInputStream() 和 getReader() 都只能讀取一次,由于 Request Body 是流的形式讀取,那么
流讀了一次就沒有了,所以只能被調(diào)用一次。
解決辦法
先將 Request Body 保存,然后通過 Servlet 自帶的 HttpServletRequestWrapper 類覆蓋 getReader() 和
getInputStream() 方法,使流從保存的body讀取。
然后再Filter中將ServletRequest替換為AuthenticationRequestWrapper。
代碼示例:
public class MyRequestWrapper extends HttpServletRequestWrapper { private byte[] body; public MyRequestWrapper(HttpServletRequest request) throws IOException { super(request); 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(body, StandardCharsets.UTF_8); } }
// 獲取請求body try { MyRequestWrapper myRequestWrapper = new MyRequestWrapper(request); return myRequestWrapper.getBody(); } catch (IOException e) { log.error("get request body exception", e); throw new RuntimeException(e); }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 解決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的解決辦法
- 如何解決getReader() has already been called for this request問題
相關(guān)文章
Spring的@Validation和javax包下的@Valid區(qū)別以及自定義校驗(yàn)注解
這篇文章主要介紹了Spring的@Validation和javax包下的@Valid區(qū)別以及自定義校驗(yàn)注解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01mybatis?報(bào)錯(cuò)顯示sql中有兩個(gè)limit的解決
這篇文章主要介紹了mybatis?報(bào)錯(cuò)顯示sql中有兩個(gè)limit的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10解決Java中socket使用getInputStream()阻塞問題
這篇文章主要介紹了解決Java中socket使用getInputStream()阻塞問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12SpringBoot內(nèi)置tomcat啟動(dòng)原理詳解
這篇文章主要介紹了SpringBoot內(nèi)置tomcat啟動(dòng)原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04深入了解Java設(shè)計(jì)模式之職責(zé)鏈模式
Java設(shè)計(jì)模式中有很多種類別,例如單例模式、裝飾模式、觀察者模式等。本文將為大家詳細(xì)介紹其中的職責(zé)鏈模式,感興趣的可以了解一下2022-09-09