1

私は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に変換しようとしましたが、どちらも機能しませんでした。ですから、これを行う方法について誰かが何かアドバイスを持っているなら、遠慮なく私を助けてください。

前もって感謝します。

4

1 に答える 1

1

すべての出力が出力ストリームを使用して行われると仮定しましょう(実際にはわかりませんが、ライターも直接書き込むことができます)。次に、「サイズ」カウンターを実際にインクリメントするプロキシを提供する必要があります。これはパフォーマンスに影響を与える可能性があることに注意してください。

new 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 に答える