用java中的过滤器记录servlet请求和响应的内容大小

用java中的过滤器记录servlet请求和响应的内容大小,java,servlets,size,response,servlet-filters,Java,Servlets,Size,Response,Servlet Filters,我正在从事一个java项目,现在我被要求跟踪向服务器发送和从服务器发送的数据量。所以我编写了一个过滤器,并将其映射到它应该监视的所有调用,就像其他人告诉我的那样。这个过滤器正常工作,但是我在获取响应的大小时遇到了问题。这是doFilter的基本实现,我使用了一个包装器来响应 DoFilter: public void doFilter(ServletRequest request, ServletResponse response, FilterCh

我正在从事一个java项目,现在我被要求跟踪向服务器发送和从服务器发送的数据量。所以我编写了一个过滤器,并将其映射到它应该监视的所有调用,就像其他人告诉我的那样。这个过滤器正常工作,但是我在获取响应的大小时遇到了问题。这是doFilter的基本实现,我使用了一个包装器来响应

DoFilter:

public void doFilter(ServletRequest request,
                       ServletResponse response, FilterChain chain)
      throws IOException, ServletException
  {
    if (filterConfig == null)
      return;

    LogResponseWrapper logResponseWrapper = new LogResponseWrapper((HttpServletResponse) response);
    chain.doFilter(request, logResponseWrapper);

  }
基于在线示例的包装器:

public class LogResponseWrapper extends HttpServletResponseWrapper
  {
    public long size = 0;
    public PrintWriter myWriter = null;
    public OutputStream myOutputStream = null;

    LogResponseWrapper(HttpServletResponse response)
    {
      super(response);
    }

    @Override
    public PrintWriter getWriter()
    {
      PrintWriter writer = null;
      try
      {
        System.out.println("calling the writer");
        writer = super.getWriter();
        myWriter = writer;
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
      return writer;
    }

    @Override
    public ServletOutputStream getOutputStream()
    {
      ServletOutputStream os = null;
      try
      {
        System.out.println("calling the getOutputStream");
        os = super.getOutputStream();
        myOutputStream = os;
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
      return os;
    }
  }
所以,你看,这是非常基本的,并且做了它应该做的事情。但是在调用chain.doFilter之后,我似乎无法确定有多少字节被传输到响应。我已经尝试将其转换为DataOutputStream和ByteArrayOutputStream,正如其他人所建议的那样,但这也不起作用。因此,如果有人对如何做到这一点有任何建议,请随时帮助我


提前感谢您。

让我们假设所有输出都是使用输出流完成的(不太确定,也许编写器也可以直接编写)。然后,您必须提供一个实际增加“大小”计数器的代理。请注意,这可能会影响性能

然后,您将返回一个
新的MyOutputStream(super.getOutputStream())
,而不是
super.getOutputStream()
,其中MyOutputStream是一个代理,在关闭时更新总数。示例代码(警告:未测试):


神奇之处在于“updateTotals”——这是更新LogResponseWrapper大小的地方。如果要在多线程环境中执行此操作,则应添加同步以避免争用条件。

让我们假设所有输出都是使用输出流完成的(不确定这一点,可能编写器也可以直接写入)。然后,您必须提供一个实际增加“大小”计数器的代理。请注意,这可能会影响性能

然后,您将返回一个
新的MyOutputStream(super.getOutputStream())
,而不是
super.getOutputStream()
,其中MyOutputStream是一个代理,在关闭时更新总数。示例代码(警告:未测试):


神奇之处在于“updateTotals”——这是更新LogResponseWrapper大小的地方。如果这将在多线程环境中执行,您应该添加同步以避免竞争条件。

感谢您的回答,它确实为我指明了正确的方向。作者确实在做一些输出,但是我在记录流量方面没有任何问题。谢谢你的回答,它确实为我指明了正确的方向。作者确实在做输出的某些部分,但我在记录流量方面没有任何问题。
private class MyOutputStream extends OutputStream {
    private long written = 0;
    private OutputStream inner;
    public MyOutputStream(OutputStream inner) {
        this.inner = inner;
    }
    public void close() {
        inner.close();
        updateTotals();
    }
    public void flush() {
        inner.flush();
    }
    public void write(byte[] b) {
        write(b, 0, b.length);
    }
    public void write(byte[] b, int off, int len) {
        inner.write(b, off, len);
        written += len;
    }
    public abstract void write(int b) {
        written ++;
        inner.write(b);
    }
}