如何使用过滤器来衡量性能?

时间:2012-11-20 10:17:17

标签: java servlets servlet-filters timing

我想知道我是否可以使用过滤器(在我的情况下是CorsFilter)来测量时间并将时间用于消息本身。我知道以下工作正常:

public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
  long startTime = System.nanoTime();
  chain.doFilter(request, response);
  long endTime = System.nanoTime();
  System.out.println("Time: " + (endTime - startTime) );
}

当然以秒为单位输出总时间。我想把时间放在返回的响应的标题中,以便接收者可以查看标题并查看处理时间。以下代码不起作用:

public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
  long startTime = System.nanoTime();
  if(response instanceof HttpServletResponse) {
    HttpServletResponse httpResp = (HttpServletResponse)response;
    httpResp.addHeader("Start-time", Long.toString(startTime));
  }

  chain.doFilter(request, response);
  long endTime = System.nanoTime();
  if(response instanceof HttpServletResponse) {
    HttpServletResponse httpResp = (HttpServletResponse)response;
    httpResp.addHeader("End-time", Long.toString(endTime));
  }
}

标题仅包含开始时间而非结束时间。我假设这是因为消息已经发送,因此修改对象将无效。

有没有人有一个优雅/聪明的解决方案,通过使用过滤器将时间放入标题?

谢谢, 菲尔

更新

我已经研究过使用HttpServletResponseWrapper来解决这个问题。这仍然无法在响应头上输出XXX-EndTime或YYY-EndTime。

@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
  long startTime = System.nanoTime();

  if(response instanceof HttpServletResponse) {
    HttpServletResponse httpResp = (HttpServletResponse)response;
    httpResp.addHeader("Access-Control-Allow-Origin", "*");
    httpResp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
    httpResp.addHeader("Allow", "GET, HEAD, OPTIONS");
    httpResp.addHeader("Access-Control-Allow-Headers", "*");
    httpResp.addHeader("A-Runtime", Long.toString(startTime));
  }

  OutputStream out = response.getOutputStream();

  GenericResponseWrapper wrapper = new GenericResponseWrapper((HttpServletResponse) response);

  chain.doFilter(request,wrapper);

  out.write(wrapper.getData());

  if(response instanceof HttpServletResponse) {
HttpServletResponse httpResp = (HttpServletResponse)response;
httpResp.addHeader("XXX-EndTime", Long.toString(System.nanoTime() - startTime));

    wrapper.addHeader("YYY-EndTime", Long.toString(System.nanoTime() - startTime));
  }

  out.close();
}

1 个答案:

答案 0 :(得分:2)

看看HttpServletResponseWrapper


好的,然后代码:

此代码缓冲输出(以两种方式),因此在伪输出工作之后添加标头。实际上addHeader可以通过输出实现,所以我们幸运它的工作原理。边界案例代码。如果运气不好,则必须覆盖addHeader。

介意,当我尝试时,我的测试应用中只调用了getOutputStream。可以选择选择getPrintWriter或getOutputStream。

private static class PostponingResponseWrapper extends HttpServletResponseWrapper {

    private ByteArrayOutputStream bos;
    private ServletOutputStream outputStream;
    private StringWriter sw;
    private PrintWriter printWriter;
    private boolean usingOutputStream;
    private boolean usingWriter;

    public PostponingResponseWrapper (HttpServletResponse response) {
        super(response);
        bos = new ByteArrayOutputStream();
        outputStream = new ServletOutputStream() {
            @Override
            public void write(int b) throws IOException {
                bos.write(b);
            }
        };
        sw = new StringWriter();
        printWriter = new PrintWriter(sw);
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        usingWriter = true;
        LOGGER.info("getWriter usingWriter {}, usingOutputStream {}", usingWriter, usingOutputStream);
        return printWriter;
    }

    @Override
    public void flushBuffer() throws IOException {
        LOGGER.info("flushBuffer");
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        usingOutputStream = true;
        LOGGER.info("getOutputStream usingWriter {}, usingOutputStream {}", usingWriter, usingOutputStream);
        ServletOutputStream out = new ServletOutputStream() {
            @Override
            public void write(int b) throws IOException {
                outputStream.write(b);
            }
        };
        return out;
    }

    public void finish() throws IOException {
        LOGGER.info("finish");
        if (usingWriter) {
            super.getWriter().print(sw.toString());
        } else if (usingOutputStream) {
            super.getOutputStream().write(bos.toByteArray());
        }
    }
}

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    PostponingResponseWrapper responseWrapper =
            new PostponingResponseWrapper (httpServletResponse);
    responseWrapper.addHeader("Before", "Already-Worked");
    chain.doFilter(request, responseWrapper);
    responseWrapper.addHeader("After", "And-Now-This");
    responseWrapper.finish(); // Writes the actual response
}