我意识到这是一个鸡和蛋的问题,并且不可能准确地解决呈现页面所花费的时间(或响应的大小)并将该数字插入页面本身而不影响任何一个度量。不过,我正在寻找一种方法来将一个数字部分插入JSF / Facelets / Seam应用程序的页面中。
,例如,在.jsf页面的底部:
<!-- page size: 10.3Kb -->
<!-- render time: 0.2s -->
我遇到了JSFUnit的JSFTimer,这非常方便。但是,相位侦听器方法不允许将RENDER_RESPONSE阶段的结果插入到页面中。不知道如何访问到目前为止编码的响应的大小。
在RENDER_RESPONSE结束时或之后是否有一种快速而肮脏的方式来连接某种后处理事件,并将这两个数字注入到即将呈现的页面中?接近这个的一种方法可能是通过servlet过滤器,但我正在寻找更简单的东西;也许是Seam或Facelets的一招(
)谢谢,
-A
答案 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调用,在服务器准备就绪后从服务器获取响应时间和大小?将其视为在页面加载完成后执行的回调,并且值已准备好插入。