2013-05-20 9 views
7

Sto lavorando al tutorial sulla servlet Java EE e ho provato il mood example. Ho notato che doFilter viene chiamato due volte, una volta che la chiamata servlet è nella catena e la seconda volta non lo è.doFilter ha chiamato due volte, comportamento previsto?

Ho aggiunto alcuni printlns in TimeOfDayFilter.java e in MoodServlet.java per mostrare questo.

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

Il risultato dal server GlassFish (3.1) Finestra quando si chiama il servlet è il seguente:

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

È questo comportamento previsto? In tal caso, qual è la ragione della chiamata in più?

+1

Basta fare 'System.out.println (request.getRequestURI())' per sapere quale richiesta ha colpito esattamente il filtro.E, premere F12 nel browser per tenere traccia di tutte le richieste HTTP licenziate. – BalusC

risposta

3

Sì, il filtro viene eseguito due volte nel ciclo di vita, le prime chiamate quando la richiesta dal client arriva al servlet e la seconda volta quando la risposta viene fornita al client dopo l'esecuzione del servlet.

L'ordine di esecuzione è in qualche modo simile a questo.

Filter lifecycle

+2

Grazie per la risposta, ma qualche altra domanda: - Si potrebbe anche interpretare le frecce di risposta come il codice che avviene dopo la chiamata chain.doFilter (come nella riga del mio frammento di codice che stampa "TimeOfDay after"), ma è davvero una nuova chiamata del metodo DoFilter dei filtri? - C'è un modo per determinare se è la prima o la seconda volta che viene chiamato (richiesta o risposta)? - C'è un modo per non avere la chiamata sulla via del ritorno? – user1348661

+1

seguente argomento della documentazione servlet spiega il concetto in dettaglio, [comprensione e l'utilizzo filtri servlet] (http://sqltech.cl/doc/oas10gR3/web.1013/b14426/filters.htm) È possibile utilizzare alcuni richiesta parametro o uso seguente istruzione 'if' per quello' if (res instanceof HttpServletResponse) 'per defirmare –

+0

Ok, ottengo l'immagine (ma l'istruzione if non funziona con me, restituisce sempre true, mi ci tufferò dentro). Thx – user1348661

3
chain.doFilter(request,response); 

Questo passerà il controllo al servlet filtro è associato. Ma dopo l'esecuzione del servlet corrispondente, il controllo ritorna alla fine della riga precedente e tutte le linee successive nel doFilter corrente() vengono eseguite.

Se si vuole passare il controllo in modo permanente al servlet e non lasciarlo tornare al filtro, basta aggiungere un

return; 

alla fine del chain.doFilter (richiesta, risposta) la linea nella corrente filtro.

+2

Questa risposta non spiega in alcun modo i sintomi descritti nella domanda. – BalusC

0

Il motivo per cui il filtro viene chiamato due volte sono le immagini utilizzate per la creazione di risposta, come per esempio

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

Si prega di vedere l'output di registro

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 nel tag img non è altro rispetto alla seconda richiesta per il server di cui occuparsi. Si prega di notare il modello URL utilizzato nel @WebFilter

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

Sarà intercettare tutte le richieste che entrano in applicazione umore. Come esercizio semplicemente provare a rimuovere le immagini dal modello di risposta o il cambiamento URL per intercettare le richieste solo di finire in MoodServlet

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

Entrambi si tradurrà in una chiamata di doFilter come originariamente previsto

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 in Servlet è una cattiva pratica. L'HTML appartiene a JSP. JSP è uno strumento molto più adatto per la definizione del codice HTML che dovrebbe essere emesso. Non è necessario sfocare le doppie virgolette. 2) Non sono necessariamente solo immagini. Qualsiasi risorsa/risorsa il cui URL corrisponde al pattern URL del filtro potrebbe essere un candidato (CSS, JS, favicon, ecc.). – BalusC

+0

Ciao BalusC, grazie per l'aggiunta di idee profonde e pratiche, come al solito. L'intero esempio è tratto dal tutorial Java EE 7 ufficiale che ho fatto oggi e mi ha fatto fare la stessa domanda che ho trovato qui :) È solo una semplice vetrina di servlet, filtri e listener che i creatori di tutorial hanno usato. La creazione della risposta html in servlet è lì solo per semplicità, naturalmente. – SilverFox

+0

(Sì, tecnicamente anche jsp diventa servlet, ma tu capisci il mio punto :)) – SilverFox

Problemi correlati