如何将响应大小和时间插入页面本身,至少部分?

时间:2010-07-10 21:02:10

标签: jsf servlets httpresponse

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

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

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

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

在RENDER_RESPONSE结束时或之后是否有一种快速而肮脏的方式来连接某种后处理事件,并将这两个数字注入到即将呈现的页面中?接近这个的一种方法可能是通过servlet过滤器,但我正在寻找更简单的东西;也许是Seam或Facelets的一招(

谢谢,
-A

3 个答案:

答案 0 :(得分:22)

这是Apache Commons IO CountingOutputStream的完美用例。您需要创建一个Filter,使用HttpServletResponseWrapper将响应的OutputStream替换为此Writer并替换OutputStream,它应该包裹HttpServletResponseWrapper }。然后抓住请求范围中的getByteCount()实例,以便从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(); } }

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

您可以在任何(甚至非JSF)页面中使用它,如下所示:

{{1}}

答案 1 :(得分:2)

我写了一篇博文,解释了如何创建一个拦截器来测量每个方法调用你的缝组件使用的地方。

您可以找到博文here。 您需要向下滚动到第二部分。

基本上,您需要做的就是注释要测量的方法 @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() 

答案 2 :(得分:0)

或者有一个异步Javascript调用,在服务器准备就绪后从服务器获取响应时间和大小?将其视为在页面加载完成后执行的回调,并且值已准备好插入。