13

これはニワトリが先か卵が先かの問題であり、ページをレンダリングするのにかかった時間 (または応答のサイズ) を正確に解決し、その数値をページ自体に挿入することは、どちらの尺度にも影響を与えずにできないことを認識しています。それにもかかわらず、JSF/Facelets/Seam アプリケーションのページにいずれかの番号を部分的に挿入する方法を探しています。

たとえば、どこかの .jsf ページの下部:

<!-- page size: 10.3Kb -->
<!-- render time: 0.2s -->

私は JSFUnit のJSFTimerに出くわしました。これは本当に便利です。ただし、フェーズ リスナー アプローチでは、RENDER_RESPONSE フェーズの結果をページに挿入することはできません。これまでにエンコードされた応答のサイズにアクセスする方法もわかりません。

RENDER_RESPONSE の終了時または終了後にある種の後処理イベントに接続し、レンダリングしようとしているページに両方の数値を挿入するための迅速で汚い方法はありますか? これにアプローチする 1 つの方法は、おそらくサーブレット フィルターを使用することですが、私はもっと単純なものを探しています。おそらくSeamまたはFaceletsのトリック...

ありがとう、
-A

4

3 に答える 3

23

これは、Apache Commons IO CountingOutputStreamの完璧な使用例です。応答の をこれに置き換えるためFilterに使用する を作成し、ラップされた をラップする も置き換える必要があります。次に、リクエスト スコープでインスタンスを取得して、からを取得できるようにします。HttpServletResponseWrapperOutputStreamWriterOutputStreamHttpServletResponseWrappergetByteCount()CountingOutputStream

のキックオフの例を次に示しCountingFilterます。

public class CountingFilter implements Filter {

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // NOOP.
    }

    @Override
    public void doFilter(ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpres = (HttpServletResponse) response;
        CountingServletResponse counter = new CountingServletResponse(httpres);
        HttpServletRequest httpreq = (HttpServletRequest) request;
        httpreq.setAttribute("counter", counter);
        chain.doFilter(request, counter);
        counter.flushBuffer(); // Push the last bits containing HTML comment.
    }

    @Override
    public void destroy() {
        // NOOP.
    }

}

CountingServletResponse:_

public class CountingServletResponse extends HttpServletResponseWrapper {

    private final long startTime;
    private final CountingServletOutputStream output;
    private final PrintWriter writer;

    public CountingServletResponse(HttpServletResponse response) throws IOException {
        super(response);
        startTime = System.nanoTime();
        output = new CountingServletOutputStream(response.getOutputStream());
        writer = new PrintWriter(output, true);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return output;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return writer;
    }

    @Override
    public void flushBuffer() throws IOException {
        writer.flush();
    }

    public long getElapsedTime() {
        return System.nanoTime() - startTime;
    }

    public long getByteCount() throws IOException {
        flushBuffer(); // Ensure that all bytes are written at this point.
        return output.getByteCount();
    }

}

CountingServletOutputStream:_

public class CountingServletOutputStream extends ServletOutputStream {

    private final CountingOutputStream output;

    public CountingServletOutputStream(ServletOutputStream output) {
        this.output = new CountingOutputStream(output);
    }

    @Override
    public void write(int b) throws IOException {
        output.write(b);
    }

    @Override
    public void flush() throws IOException {
        output.flush();
    }

    public long getByteCount() {
        return output.getByteCount();
    }

}

次のように、任意の (非 JSF を含む) ページで使用できます。

<!DOCTYPE html>
<html 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Counting demo</title>
    </h:head>
    <h:body>
        <h1>Hello World</h1>
    </h:body>
</html>
<!-- page size: #{counter.byteCount / 1000}KB -->
<!-- render time: #{counter.elapsedTime / 1000000}ms -->
于 2010-07-11T01:36:27.180 に答える
2

使用時にシームコンポーネントを呼び出す各メソッドを測定するインターセプターを作成する方法を説明するブログ投稿を書きました。

ブログ投稿はここにあります。2番目の部分まで下にスクロールする必要があります。

基本的に、あなたがする必要があるのはあなたが測定したい方法に注釈を付けることだけで @MeasureCallsあり、それはインターセプターによって自動的にピックアップされます

@Name("fooBean")
@MeasureCalls
public class FooBean

出力は次のようになり、ミリ秒単位の時間と各メソッドが呼び出された回数が表示されます。

284.94 ms   1   FooBean.getRandomDroplets()
284.56 ms   1   GahBean.getRandomDroplets()
201.60 ms   2   SohBean.searchRatedDoodlesWithinHead()
185.94 ms   1   FroBean.doSearchPopular()
157.63 ms   1   FroBean.doSearchRecent()
 42.34 ms   1   FooBean.fetchMostRecentYodel()
 41.94 ms   1   GahBean.getMostRecentYodel()
 15.89 ms   1   FooBean.getNoOfYodels()
 15.00 ms   1   GahBean.getNoOfYodels()
  9.14 ms   1   SohBean.mainYodels()
  1.11 ms   2   SohBean.trackHoorayEvent()
  0.32 ms   1   FroBean.reset()
  0.22 ms  43   NohBean.thumbPicture()
  0.03 ms  18   FooBean.getMostRecentYodels()
  0.01 ms   1   NohBean.profilePicture()
  0.01 ms   1   FroBean.setToDefault()
  0.01 ms   1   FroBean.getRecentMarker() 
于 2011-01-21T15:53:30.567 に答える
0

または、準備ができた後にサーバーから応答時間とサイズを取得する非同期 Javascript 呼び出しがありますか? ページの読み込みが完了し、値を挿入する準備ができた後に実行されるコールバックのように扱います。

于 2010-07-10T21:16:51.383 に答える