Forward versus redirect
A Controller (in this context, an implementation of HttpServlet) may perform either a forward or a redirect operation at the end of processing a request. It's important to understand the difference between these two cases, in particular with respect to browser reloads of web pages.Forward
- a forward is performed internally by the servlet
- the browser is completely unaware that it has taken place, so its original URL remains intact
- any browser reload of the resulting page will simple repeat the original request, with the original URL
- a redirect is a two step process, where the web application instructs the browser to fetch a second URL, which differs from the original
- a browser reload of the second URL will not repeat the original request, but will rather fetch the second URL
- redirect is marginally slower than a forward, since it requires two browser requests, not one
- objects placed in the original request scope are not available to the second request
- for SELECT operations, use a forward
- for INSERT, UPDATE, or DELETE operations, use a redirect
The most common symptom of not using forward/redirect properly is a warning message in a browser, asking the user if they really wish to POST their form data a second time.
Example
This example is after the style of the WEB4J Controller class. The important methods of the Servlet API are:
- ServletRequest.getRequestDispatcher(String)
- RequestDispatcher.forward(request, response)
- HttpServletResponse.sendRedirect(String)
import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; import hirondelle.web4j.action.Action; import hirondelle.web4j.action.ResponsePage; import hirondelle.web4j.request.RequestParser; import hirondelle.web4j.model.BadRequestException; public class RedirectForward extends HttpServlet { //..many items elided @Override public final void doGet( HttpServletRequest aRequest, HttpServletResponse aResponse ) throws ServletException, IOException { processRequest(aRequest, aResponse); } @Override public final void doPost( HttpServletRequest aRequest, HttpServletResponse aResponse ) throws ServletException, IOException { processRequest(aRequest, aResponse); } /** * Handle all HTTP GET and POST requests. */ protected void processRequest( HttpServletRequest aRequest, HttpServletResponse aResponse ) throws ServletException, IOException { RequestParser requestParser = RequestParser.getInstance(aRequest, aResponse); try { Action action = requestParser.getWebAction(); ResponsePage responsePage = action.execute(); if ( responsePage.getIsRedirect() ) { redirect(responsePage, aResponse); } else { forward(responsePage, aRequest, aResponse); } } catch (BadRequestException ex){ //..elided //use Response.sendError() } catch (Throwable ex) { //..elided //use Response.sendError() } } // PRIVATE // private void redirect( ResponsePage aDestinationPage, HttpServletResponse aResponse ) throws IOException { String urlWithSessionID = aResponse.encodeRedirectURL(aDestinationPage.toString()); aResponse.sendRedirect( urlWithSessionID ); } private void forward( ResponsePage aResponsePage, HttpServletRequest aRequest, HttpServletResponse aResponse ) throws ServletException, IOException { RequestDispatcher dispatcher = aRequest.getRequestDispatcher(aResponsePage.toString()); dispatcher.forward(aRequest, aResponse); } }
No comments:
Post a Comment