What is the conceptual difference between forward()
and sendRedirect()
?
In the web development world, the term "redirect" is the act of sending the client an empty HTTP response with just a Location
header containing the new URL to which the client has to send a brand new GET request. So basically:
some.jsp
.Location: other.jsp
headerother.jsp
(this get reflected in browser address bar!)other.jsp
.You can track it with the web browser's builtin/addon developer toolset. Press F12 in Chrome/IE9/Firebug and check the "Network" section to see it.
Exactly the above is achieved by sendRedirect("other.jsp")
. The RequestDispatcher#forward()
doesn't send a redirect. Instead, it uses the content of the target page as HTTP response.
some.jsp
.other.jsp
.However, as the original HTTP request was to some.jsp
, the URL in browser address bar remains unchanged. Also, any request attributes set in the controller behind some.jsp
will be available in other.jsp
. This does not happen during a redirect because you're basically forcing the client to create a new HTTP request on other.jsp
, hereby throwing away the original request on some.jsp
including all of its attribtues.
The RequestDispatcher
is extremely useful in the MVC paradigm and/or when you want to hide JSP's from direct access. You can put JSP's in the /WEB-INF
folder and use a Servlet
which controls, preprocesses and postprocesses the requests. The JSPs in the /WEB-INF
folder are not directly accessible by URL, but the Servlet
can access them using RequestDispatcher#forward()
.
You can for example have a JSP file in /WEB-INF/login.jsp
and a LoginServlet
which is mapped on an url-pattern
of /login
. When you invoke http://example.com/context/login
, then the servlet's doGet()
will be invoked. You can do any preprocessing stuff in there and finally forward the request like:
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
When you submit a form, you normally want to use POST
:
<form action="login" method="post">
This way the servlet's doPost()
will be invoked and you can do any postprocessing stuff in there (e.g. validation, business logic, login the user, etc).
If there are any errors, then you normally want to forward the request back to the same page and display the errors there next to the input fields and so on. You can use the RequestDispatcher
for this.
If a POST
is successful, you normally want to redirect the request, so that the request won't be resubmitted when the user refreshes the request (e.g. pressing F5 or navigating back in history).
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
response.sendRedirect("home"); // Redirects to http://example.com/context/home after succesful login.
} else {
request.setAttribute("error", "Unknown login, please try again."); // Set error.
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to same page so that you can display error.
}
A redirect thus instructs the client to fire a new GET
request on the given URL. Refreshing the request would then only refresh the redirected request and not the initial request. This will avoid "double submits" and confusion and bad user experiences. This is also called the POST-Redirect-GET
pattern.