2013-05-20 22 views
7

我正在通過Java EE servlet教程並嘗試使用mood example。我注意到doFilter被調用兩次,一旦servlet調用在鏈中,第二次調用不成功。doFilter調用兩次,有意的行爲?

我在TimeOfDayFilter.java和MoodServlet.java中添加了一些printlns來顯示它。

TimeOfDayFilter.java:

... 
    System.out.println("TimeOfDay before"); //added 
    chain.doFilter(req, res); 
    System.out.println("TimeOfDay after"); //added 
    ... 

MoodServlet.java:

... 
    response.setContentType("text/html;charset=UTF-8"); 

    System.out.println("MoodServlet"); //added 

    PrintWriter out = response.getWriter(); 
    ... 

從GlassFish服務器(3.1)調用Servlet時窗口的結果如下:

INFO: mood was successfully deployed in 406 milliseconds. 
    INFO: TimeOfDay before 
    INFO: MoodServlet 
    INFO: TimeOfDay after 
    INFO: TimeOfDay before 
    INFO: TimeOfDay after 

這是預期的行爲?如果是這樣,那麼額外電話的原因是什麼?

+1

只是做'System.out.println(request.getRequestURI())'來了解哪個請求準確地觸發了過濾器。然後,在webbrowser中按F12以跟蹤所有觸發的HTTP請求。 – BalusC

回答

3

是的,Filter在生命週期中執行兩次,當客戶端請求到達servlet時第一次調用,第二次在servlet執行後響應被提供給客戶端。

執行順序看起來像這樣。

Filter lifecycle

+2

感謝您的回答,但還有幾個問題: - 也可以將響應箭頭解釋爲在chain.doFilter調用之後發生的代碼(如我的代碼片段的行中打印「TimeOfDay after」),但它真的是DoFilter方法的新過濾器嗎? - 有沒有辦法確定它是第一次還是第二次被調用(請求或響應部分)? - 有沒有辦法在回來的時候不打電話? – user1348661

+1

關於servlet文檔的下列主題詳細解釋了整個概念, [瞭解和使用Servlet過濾器](http://sqltech.cl/doc/oas10gR3/web.1013/b14426/filters.htm) 您可以使用一些請求參數或使用下面的if語句來解決 –

+0

好吧,我得到了圖片(但if語句不適用於我,總是返回true,我會潛入其中)。 Thx – user1348661

3
chain.doFilter(request,response); 

這將通過控制到過濾器與相關聯的的servlet。 但是,在執行相應的servlet之後,控制權將返回到上述行的末尾,並且此後執行當前doFilter()中的所有行。在當前

如果你想永久傳遞控制到servlet,而不是讓它回到過濾器,只在chain.doFilter的末尾添加

return; 

(請求,響應)線過濾。

+2

此答案不以任何方式解釋問題中描述的症狀。 – BalusC

0

之所以過濾器被調用兩次是在響應創建中使用的圖像,例如

out.println("<img src=\"resources/images/duke.snooze.gif\" alt=\"Duke sleeping\"/><br/>"); 

請參閱日誌輸出

2016-01-16T11:25:34.894+0100|Info: TimeOfDay doFilter method before sending to chain 

2016-01-16T11:25:34.895+0100|Info: MoodServlet get method called 

2016-01-16T11:25:34.895+0100|Info: TimeOfDay doFilter method after sending to chain 

2016-01-16T11:25:34.942+0100|Info: TimeOfDay doFilter method before sending to chain 

2016-01-16T11:25:34.942+0100|Info: TimeOfDay doFilter method after sending to chain 

src在img標籤是什麼都沒有而不是第二次請求服務器處理。請注意@WebFilter中使用的網址格式

@WebFilter(filterName = "TimeOfDayFilter", 
urlPatterns = {"/*"}, 
initParams = { 
    @WebInitParam(name = "mood", value = "awake")}) 

它會攔截所有進入情緒應用程序的請求。作爲一個練習簡單地嘗試從響應或更改URL模式刪除圖像截取只要求在MoodServlet

結束了
@WebFilter(filterName = "TimeOfDayFilter", 
urlPatterns = {"/report"}, 
initParams = { 
    @WebInitParam(name = "mood", value = "awake")}) 

雙方將導致的doFilter的一個電話,你原本預計

2016-01-16T11:28:53.485+0100|Info: TimeOfDay doFilter method before sending to chain 

2016-01-16T11:28:53.486+0100|Info: MoodServlet get method called 

2016-01-16T11:28:53.487+0100|Info: TimeOfDay doFilter method after sending to chain 
+1

1)Servlet中的HTML是不好的做法。 HTML屬於JSP。 JSP是一個更適合定義應該發佈的HTML代碼的工具。根本不需要雙引號。 2)它不一定只是圖像。任何URL與過濾器URL模式匹配的資產/資源都可能成爲候選人(CSS,JS,圖標等)。 – BalusC

+0

嗨BalusC,謝謝深入和方便的想法,通常情況下額外。整個例子來自我今天經歷的官方Java EE 7教程,它讓我問到了我在這裏找到的同樣的問題:)它只是servlet,過濾器和監聽器教程創建者使用的基本展示。在servlet中創建html響應僅僅是爲了簡單。 – SilverFox

+0

(是的,技術上也jsp變成servlet,但你明白我的觀點:)) – SilverFox