2012-11-20 42 views
6

我想知道如果我可以使用過濾器(在我的情況下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(); 
} 

回答

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 
} 
+2

-1回答這個問題開了更多的問題,然後他們回答。 – Yevgeniy

+0

@YevgeniyM。你是對的,應該只是一個評論,有這樣一個包裝類+1。 –

+0

好吧,我已經使用HttpServletResponseWrapper實現了一個解決方案,但仍然無法使它工作!我將用我的新代碼更新上面的問題。 – Phil