如何至少部分地将响应大小和时间插入页面本身? [英] How to insert response size and time into the page itself, at least partially?

查看:99
本文介绍了如何至少部分地将响应大小和时间插入页面本身?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我意识到这是鸡和鸡蛋的问题,不可能准确地解决渲染页面(或响应大小)并将该数字插入页面本身所花费的时间而不会影响任何一种度量.尽管如此,我正在寻找一种在JSF/Facelets/Seam应用程序的页面中部分插入其中一个数字的方法.

I realize it's a chicken and egg problem and that it's not possible to accurately resolve the time it took to render a page (or the size of response) and insert that number into the page itself without affecting either measure. Nevertheless, I'm looking for a way to insert either number partially in a page of a JSF/Facelets/Seam application.

例如,在.jsf页面底部的某处:

E.g., at the bottom of a .jsf page somewhere:

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

我遇到过JSFUnit的 JSFTimer ,它非常方便.但是,阶段侦听器方法不允许将RENDER_RESPONSE阶段的结果插入页面.也不知道如何访问到目前为止编码的响应的大小.

I've come across JSFUnit's JSFTimer, which is really handy. However, the phase listener approach doesn't allow the results of RENDER_RESPONSE phase to be inserted into the page. Not sure how to access the size of the response encoded so far either.

是否有一种快速而又肮脏的方法来挂接RENDER_RESPONSE结束时或结束后的某种后处理事件,并将这两个数字注入要渲染的页面中?解决此问题的一种方法可能是通过servlet过滤器,但我正在寻找更简单的方法.也许是Seam或Facelets的把戏...

Is there a quick and dirty way to hook up to some sort of post-processing event at or after the end of RENDER_RESPONSE and to inject both numbers into the page about to be rendered? One way of approaching this is perhaps through servlet filters, but I'm looking for something simpler; perhaps a trick with Seam or Facelets...

谢谢,
-A

Thanks,
-A

推荐答案

这是 Apache的完美用例Commons IO CountingOutputStream .您需要创建使用 HttpServletResponseWrapperFilter 用该内容替换响应的OutputStream,并替换Writer,后者也应该包装已包装的OutputStream.然后在请求范围内获取HttpServletResponseWrapper实例,以便可以从CountingOutputStream获取getByteCount().

This is a perfect use case for the Apache Commons IO CountingOutputStream. You need to create a Filter which uses HttpServletResponseWrapper to replace the OutputStream of the response with this one and replaces the Writer as well which should wrap the wrapped OutputStream. Then get hold of the HttpServletResponseWrapper instance in the request scope so that you can get the getByteCount() from the 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)页面中使用它,如下所示:

You can use it in any (even non-JSF) page as follows:

<!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 -->

这篇关于如何至少部分地将响应大小和时间插入页面本身?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆