如何至少部分地将响应大小和时间插入页面本身? [英] How to insert response size and time into the page itself, at least partially?
问题描述
我意识到这是鸡和鸡蛋的问题,不可能准确地解决渲染页面(或响应大小)并将该数字插入页面本身所花费的时间而不会影响任何一种度量.尽管如此,我正在寻找一种在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
一个>.您需要创建使用 HttpServletResponseWrapper
的Filter
用该内容替换响应的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屋!