- Objectives
- Introduction
- Overriding HttpServlet GET, POST, and PUT Methods
- Triggering HttpServlet GET, POST, and PUT Methods
- Interfacing with HTML Requests
- Web Application Scope
- Servlet Life-cycle
- Using a RequestDispatcher
- Web Application Context
- Context Within a Distributable Web Application
- Chapter Summary
- Apply Your Knowledge
Using a RequestDispatcher
1.6 Use a RequestDispatcher to include or forward to a Web resource.
The RequestDispatcher is a powerful tool. You can perform programmatic server-side includes or route the whole request to another servlet or JSP with a forward. There are three ways to get the RequestDispatcher. The first two are through the Context, with ServletContext.getRequestDispatcher(java.lang.String) or with ServletContext.getNamedDispatcher(java.lang.String). Either returns a RequestDispatcher object that acts as a wrapper for the named servlet (in web.xml, the Web application deployment descriptor). The final way is with ServletRequest.getRequestDispatcher(java.lang.String). Notice that you can use a relative pathname here. You must use absolutes with ServletContext.getRequestDispatcher(java.lang.String). Be careful with your paths. If the path begins with a "/", it is interpreted as relative to the current context root. You will get a null if the Servlet Container cannot return a RequestDispatcher.
A RequestDispatcher object can be used to forward a request to the resource or to include output from the resource in a response. The specification allows the resource to be dynamic or static. If it is dynamic, such as a servlet, the container will invoke that servlet, and then take the output and include it. If it is static, such as a text file, then the container will include the text as is. Listing 4.17 demonstrates how one servlet can transfer the request to another servlet.
Listing 4.17 Using a RequestDispatcher to Forward a Request to Another Servlet
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ServletToServlet extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { getServletConfig() .getServletContext() .getRequestDispatcher("/HelloWorldExample") .forward(request, response); } catch (Exception ex) { ex.printStackTrace (); } } }
You can also include content from a static page or another servlet. You would use a snippet like so:
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(path); if (dispatcher == null) { out.println(path + " not available"); return; } else { dispatcher.include(request, response); }
There are a few characteristics about the forward and include methods. The ServletRequest's path elements and parameters remain unchanged from the caller's. The included servlet cannot set headers. This is a good candidate for a trick question. The servlet cannot change the response status code either (if you try, it will be ignored). The best way to send along information from the calling servlet to the called servlet is using a query string or, even better, using the setAttribute() method to set request object attributes where they are easy to access.
There is a matter of timing to consider. You can call an include anytime, but the forward has to be called before the response is committed. Otherwise you'll throw an IllegalStateException exception.
Request Dispatcher Paths
ServletContext.getRequestDispatcher()This method uses absolute paths.
ServletRequest.getRequestDispatcher(String path)The path may be relative, but cannot extend outside current servlet context.
ServletRequest.getNamedDispatcher(String name)This name is the name of the servlet for which a dispatcher is requested, and is in the web.xml file (see Chapter 10, "Web Applications," for more about web.xml).
Regarding the forward method, one reason you may want to use it is so you can dedicate a servlet as the controller. In this way, the controller can filter, preprocess requests, and manage the transaction. The gotcha here is once a servlet forwards a request, it loses control. The controller has no capability to regain access directly. You can create an architecture where requests are returned (forwarded back by a slave servlet), but the native functionality isn't helpful for this. There is another problem. When you run Listing 4.17, you'll notice something missingthe URL in the address bar doesn't change. The client loses path information when it receives a forwarded request. That means all relative URLs in the HTML become invalid. Your browser will consider the links broken. Sometimes this doesn't matter, but when it does, use sendRedirect() instead.