問題:
在Java Servlet 過濾器中,存取HTTP 請求POST 請求正文中的參數可能會導致這些參數稍後在過濾器鏈中不可用。出現這種情況是因為請求正文在初始讀取期間被消耗。
解決方案:
要克服此問題並啟用請求正文參數的多次讀取,解決方案包括擴展 HttpServletRequestWrapper 並快取輸入流字節。這是一個自訂請求包裝類別:
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper { private ByteArrayOutputStream cachedBytes; public MultiReadHttpServletRequest(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { if (cachedBytes == null) cacheInputStream(); return new CachedServletInputStream(cachedBytes.toByteArray()); } @Override public BufferedReader getReader() throws IOException{ return new BufferedReader(new InputStreamReader(getInputStream())); } private void cacheInputStream() throws IOException { cachedBytes = new ByteArrayOutputStream(); IOUtils.copy(super.getInputStream(), cachedBytes); } /* An input stream which reads the cached request body */ private static class CachedServletInputStream extends ServletInputStream { private final ByteArrayInputStream buffer; public CachedServletInputStream(byte[] contents) { this.buffer = new ByteArrayInputStream(contents); } @Override public int read() { return buffer.read(); } @Override public boolean isFinished() { return buffer.available() == 0; } @Override public boolean isReady() { return true; } @Override public void setReadListener(ReadListener listener) { throw new RuntimeException("Not implemented"); } } }
用法:
在透過過濾器鏈傳遞原始請求之前使用自訂包裝器包裝原始請求:
public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request); doMyThing(multiReadRequest.getInputStream()); chain.doFilter(multiReadRequest, response); } }
這允許透過getInputStream() 或getReader()多次讀取請求正文
注意:
對於較新版本的ServletInputStream 接口,需要在自定義輸入流類中實現isReady() 和setReadListener()等附加方法。詳情請參閱答案中提供的連結。
以上是如何在 Java Servlet 過濾器中啟用 POST 請求正文的多次讀取?的詳細內容。更多資訊請關注PHP中文網其他相關文章!