Quando vengono implementate applicazioni web capita molto spesso di dover delegare l’esecuzione di determinate operazioni, in risposta ad una request, ad una diversa risorsa. In questo contesto il controller, ad esempio una servlet, ha due possibilità: eseguire una operazione di redirect o di forward. È però importante comprendere la differenza tra questi due operazioni, in particolare per quanto riguarda il comportamento del browser utente.
Redirect
Per comprendere i concetti alla base dell’operazione di redirect supponiamo di utilizzare una servlet RedirectServlet
che implementa il seguente codice:
1 2 3 4 5 6 |
public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect(req.getContextPath() + "/redirected.jsp"); } } |
Dove l’oggetto HttpServletResponse
espone il metodo sendRedirect()
che consente di dirottare la richiesta su un URL differente. La servlet è quindi registrata nel descrittore web.xml
nel seguente modo:
1 2 3 4 5 6 7 8 9 10 |
<servlet> <description>Redirect Servlet</description> <display-name>RedirectServlet</display-name> <servlet-name>RedirectServlet</servlet-name> <servlet-class>it.javaboss.RedirectServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RedirectServlet</servlet-name> <url-pattern>/redirect</url-pattern> </servlet-mapping> |
Il comportamento dell’applicazione è quello mostrato in figura, in cui l’utente, una volta aver inserito nel browser l’URL http://localhost:8080/redirect?name=Javaboss viene redirezionato su una URL differente: http://localhost:8080/redirect.jsp.
Riepilogando:
- La redirect è un processo a due fasi, in cui l’applicazione Web indica al browser di recuperare un secondo URL, che differisce dall’originale;
- Il browser esegue una reload senza ripetere la richiesta originale, ma semplicemente recupererà il nuovo URL;
- Gli oggetti inseriti nello scope della richiesta originale non saranno più disponibili per la seconda richiesta.
Il primo e secondo punto sono maggiormente evidenti se analizziamo il comportamento dell’applicazione con gli strumenti di sviluppo di Chrome. Si nota, infatti, che la richiesta alla prima URL restituisce uno status code HTTP 302 che forza il browser al reload della seconda URL.
Il terzo punto, infine, implica che la query string della URL originare (name=Javaboss
) viene persa e questo è vero per ogni altra informazione legata al contesto della request e quindi anche per gli eventuali header HTTP.
Forward
Utilizziamo ancora una servlet RedirectServlet
per implementare il codice necessario ad eseguire l’operazione di forward:
1 2 3 4 5 6 7 |
public class ForwardServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/forwarded.jsp"); dispatcher.forward(req, resp); } } |
In questo caso viene recuperato un nuovo oggetto RequestDispatcher
associato alla nuova risorsa (la seconda URL), ed eseguita l’operazione di forward()
passando gli oggetti request e response originali. La servlet è quindi registrata nel descrittore web.xml
nel seguente modo:
1 2 3 4 5 6 7 8 9 10 |
<servlet> <description>Forward Servlet</description> <display-name>ForwardServlet</display-name> <servlet-name>ForwardServlet</servlet-name> <servlet-class>it.javaboss.ForwardServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ForwardServlet</servlet-name> <url-pattern>/forward</url-pattern> </servlet-mapping> |
Il comportamento dell’applicazione è quello mostrato in figura, in cui l’utente, una volta aver inserito nel browser l’URL http://localhost:8080/forward?name=Javaboss viene inoltrato sulla seconda risorsa, ma la URL visibile nel browser non cambia.
Ricapitolando:
- Il forward è un’operazione interna al server o, nel caso di più server coinvolti, è un’operazione server-to-server.
- Il browser è completamente inconsapevole che l’operazione ha avuto luogo, quindi il suo URL originale rimane intatto.
- Qualsiasi ricaricamento del browser nella pagina risultante ripeterà semplicemente la richiesta originale, con l’URL originale.
A conferma visualizziamo le richieste eseguite dal browser con gli strumenti per lo sviluppatore di Chrome, da cui si evince che il browser richiede una sola risorsa corrispondente alla URL originale e per la quale riceve direttamente un HTTP 200.
Conclusioni
In conclusione l’operazione di redirect risulta leggermente rispetto al forward, poiché richiede due richieste del browser e non uno solo. Inoltre nel primo caso il contesto della request è completamente perso e se si ha necessità di mantenerlo deve essere slavato nella sessione utente.
Codice Sorgente
Il codice sorgente con tutti gli esempi mostrati è scaricabile qui servlet redirect vs forward