5.10. The Servlet API 2.1
Sun made the specification for Version 2.1 of the Servlet API available in November 1998. This version of the API includes some small "housekeeping" changes that make it more consistent and easier to use. For example, method names have been standardized to capitalize "URL", meaning encodeUrl() has been deprecated in favor of encodeURL(), and so forth. GenericServlet now implements ServletContext directly and provides a no-argument init() method you can override in your own servlets. The ServletContext interface contains two new methods, getMajorVersion() and getMinorVersion(), that can determine the latest API version supported.
In addition to these small updates (and a few others noted in Part 3, "API Quick Reference"), Sun included a few genuinely new features. Some are fairly minor. For example, a servlet can now specify a "root cause" exception when creating a new ServletException object. The root cause can be read with the new getRootCause() method of ServletException. This provides somewhat more information than the old approach of creating a ServletException with the value returned by getMessage() from the exception that actually caused the problem.
Other new features, including request dispatching and shared attributes, are more significant and are discussed in the sections that follow. Note that as of this writing, few servlet engines support the new features in Version 2.1 of the Servlet API.
5.10.1. Request Dispatching
The new request dispatching functionality allows a servlet to delegate request handling to other components on the server. A servlet can either forward an entire request to another servlet or include bits of content from other components in its own output. In either case, this is done with a RequestDispatcher object that is obtained from the ServletContext with its new getRequestDispatcher() method. When you call this method, you specify the path to the servlet to which you are dispatching the request.
When you dispatch a request, you can set request attributes using the setAttribute() method of ServletRequest and read them using the getAttribute() method. A list of available attributes is returned by getAttributeNames(). All three of these methods are new in Version 2.1. Rather than taking only String objects (like parameters), an attribute may be any valid Java object.
RequestDispatcher provides two methods for dispatching requests: forward() and include(). To forward an entire request to another servlet, use the forward() method. When using forward(), the ServletRequest object is updated to include the new target URL. If a ServletOutputStream or PrintWriter has already been retrieved from the ServletResponse object, the forward() method throws an IllegalStateException.
The include() method of RequestDispatcher causes the content of the dispatchee to be included in the output of the main servlet--just like a server-side include. To see how this works, let's look at part of a servlet that does a keep-alive check on several different servers:
out.println("Uptime for our servers"); // Get a RequestDispatcher to the ServerMonitorServlet RequestDispatcher d = getServletContext().getRequestDispatcher("/servlet/ServerMonitorServlet"); req.setAttribute("serverurl", new URL("http://www1.company.com")); d.include(req, res); req.setAttribute("serverurl", new URL("http://www2.company.com")); d.include(req, res);
5.10.2. Shared Attributes
The ServletContext interface includes a number of new methods that support the ability for servlets to share attributes. The new setAttribute() method allows a servlet to set an attribute that can be shared by any other servlets that live in its ServletContext. The getAttribute() method, which previously allowed servlets to retrieve hardcoded server attributes, provides access to attribute values, while getAttributeNames() returns an Enumeration of all the shared attributes.
Shared attributes open up some exciting new possibilities. Multiple servlets within a single web application can easily share configuration information, as well as complex programmatic resources, such as a CORBA object that handles user authentication or a database connection pool.
On a related note, Version 2.1 of the Servlet API deprecates all methods related to accessing other servlets directly, due to the fact that they are inherently insecure. Thus, getServlet() and getServletNames() join the already deprecated getServlets(). The problem here was that getServlet() incorrectly allowed one servlet to call another servlet's life-cycle methods.
5.10.3. Resource Abstraction
Resource abstraction is a new feature that allows a servlet to access a resource on a web server, such as an HTML file, without knowing where that resource actually lives. This functionality makes it much easier to move servlets on a web server and even among web servers, such as for load-balancing purposes.
A servlet gets access to a resource using the new getResource() method of ServletContext. You specify a URI path to the resource and get back a URL object that lets you examine the requested resource. The web server controls how URI path parameters map to actual resources. Note that the resources handled by this functionality cannot be an active resource, like another servlet or a CGI script; use the RequestDispatcher for these kinds of resources.
Let's say we have a servlet that writes a complicated header for the content served by the page. To load the actual content, all we have to do is:
URL content = getServletContext().getResource("/pages/page12.html"); out.print(content.getContent());
Copyright © 2001 O'Reilly & Associates. All rights reserved.