首頁 >Java >java教程 >如何在 Java Servlet 過濾器中啟用 POST 請求正文的多次讀取?

如何在 Java Servlet 過濾器中啟用 POST 請求正文的多次讀取?

Barbara Streisand
Barbara Streisand原創
2024-11-28 15:21:12149瀏覽

How to Enable Multiple Reads of POST Request Body in Java Servlet Filters?

Java Servlet 過濾器中多次讀取Post 請求正文

問題:

在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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn