1

我正在处理一个 java 项目,现在我被要求跟踪从我们的服务器发送和发送的数据量。因此,我编写了一个过滤器并将其映射到它应该监控的所有呼叫,就像其他人告诉我的那样。该过滤器可以正常工作,但是我在获取响应大小时遇到​​了问题。这是我对 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 ,但这也不起作用。因此,如果有人对如何执行此操作有任何指示,请随时帮助我。

先感谢您。

4

1 回答 1

1

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

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

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);
    }
}

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

于 2012-07-18T14:55:41.970 回答