我想知道我是否可以使用过滤器(在我的情况下是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();
}
答案 0 :(得分:2)
好的,然后代码:
此代码缓冲输出(以两种方式),因此在伪输出工作之后添加标头。实际上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
}