2012-11-20 5 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この回答は役に立ちましたか? @ YevgeniyM。 – Yevgeniy

+0

あなたは正しいです、ちょうどそのようなラッパークラス+1があるというコメントだったはずです。 –

+0

私はHttpServletResponseWrapperを使って解決策を実装しましたが、それでも動作させることはできません!上記の質問を新しいコードで更新します。 – Phil

関連する問題