首页 > Java > java教程 > 如何在 Java Servlet 过滤器中启用 POST 请求正文的多次读取?

如何在 Java Servlet 过滤器中启用 POST 请求正文的多次读取?

Barbara Streisand
发布: 2024-11-28 15:21:12
原创
164 人浏览过

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中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板