2013-05-20 14 views
7

Używam samouczka serwletu Java EE i wypróbowałem numer mood example. Zauważyłem, że doFillter jest wywoływany dwa razy, gdy wywołanie serwletu jest w łańcuchu i po raz drugi nie jest.doFilter wywołana dwukrotnie, zamierzone zachowanie?

Dodałem kilka printlns w TimeOfDayFilter.java i MoodServlet.java, aby to pokazać.

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(); 
    ... 

Wynik z serwera GlassFish (3.1) przy wywołaniu okna serwlet jest następujący:

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

Czy to zamierzone zachowanie? Jeśli tak, jaki jest powód dodatkowego połączenia?

+1

Wystarczy zrobić 'System.out.println (request.getRequestURI())', aby dowiedzieć się, które żądanie dokładnie trafiło w filtr.I naciśnij klawisz F12 w przeglądarce, aby śledzić wszystkie wysłane żądania HTTP. – BalusC

Odpowiedz

3

Tak, filtr jest wykonywany dwukrotnie w cyklu życia, pierwsze wywołania na żądanie klienta przychodzą do serwletu i drugi raz, gdy odpowiedź jest dostarczana do klienta po wykonaniu serwletu.

Kolejność wykonywania jest jakoś tak wygląda.

Filter lifecycle

+2

Dziękuję za odpowiedź, ale kilka dodatkowych pytań: - Można również interpretować strzałki odpowiedzi jako kod, który następuje po wywołaniu chain.doFilter (jak w wierszu fragmentu kodu, który wypisuje "TimeOfDay after"), ale jest to naprawdę świeże połączenie metody filtrowania DoFilter? - Czy istnieje sposób określenia, czy jest to pierwszy czy drugi raz wywołany (część żądania lub odpowiedzi)? - Czy istnieje sposób, aby nie odebrać połączenia w drodze powrotnej? – user1348661

+1

Poniższy temat dokumentacji serwletów objaśnia szczegółowo całą koncepcję, [Zrozumienie i używanie filtrów serwletów] (http://sqltech.cl/doc/oas10gR3/web.1013/b14426/filters.htm) Możesz użyć niektórych zażądaj parametru lub użyj następującego polecenia 'if' dla tego' if (res instanceof HttpServletResponse) 'do defreetate –

+0

OK, dostaję obrazek (ale instrukcja if nie działa ze mną, zawsze zwraca true, zagłębię się w to). Thx – user1348661

3
chain.doFilter(request,response); 

Przepuszcza kontroli serwletu filtr jest związane. Ale po wykonaniu odpowiedniego apletu, sterowanie powraca na końcu powyższej linii i wszystkie linie po nim w bieżącym doFilter() są wykonywane.

Jeśli chcesz przejść kontrolę na stałe do serwletu i nie pozwoliła mu wrócić do filtra, wystarczy dodać

return; 

na koniec chain.doFilter (prośba, odpowiedź) linia w prądzie filtr.

+2

Ta odpowiedź nie wyjaśnia w żaden sposób objawów opisanych w pytaniu. – BalusC

0

Powodem filtr nazywany jest dwa razy to obrazy wykorzystane w tworzeniu odpowiedzi, jak na przykład

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

Proszę zobaczyć wyjście dziennika

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 w tagu img to nic innego niż drugie żądanie serwera do obsługi. Zwróć uwagę na wzorzec adresu URL używany w obiekcie @WebFilter Będzie przechwytywał wszystkie żądania przychodzące do aplikacji nastrój. Jako ćwiczenie po prostu spróbować, aby usunąć obrazy z wzorca reakcji lub zmianę adresu URL do przechwycenia żąda tylko kończący się w MoodServlet

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

Zarówno spowoduje jednym wezwanie doFilter jak pierwotnie zakładano

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) HTML w Servletie jest złą praktyką. HTML należy do JSP. JSP jest narzędziem znacznie bardziej odpowiednim do definiowania kodu HTML, który powinien być emitowany. Nie musisz w ogóle zadzierać podwójnymi cytatami. 2) To niekoniecznie tylko obrazy. Dowolny zasób/zasób, którego adres URL pasuje do wzorca adresu URL filtra, może być kandydatem (CSS, JS, favicons itp.). – BalusC

+0

Cześć BalusC, dzięki za dodatkowe w głębokich i poręcznych pomysłach, jak zwykle. Cały przykład pochodzi z oficjalnego samouczka Java EE 7, do którego doszedłem dzisiaj i sprawił, że zadałam to samo pytanie, które znalazłem tutaj :) Jest to tylko podstawowa prezentacja twórców samouczków serwletów, filtrów i słuchaczy. Tworzenie odpowiedzi html w serwletie jest dostępne tylko dla uproszczenia. – SilverFox

+0

(Tak, technicznie również jsp zamienia się w serwlet, ale rozumiesz mój punkt :)) – SilverFox