A servlet can set HTTP headers to provide extra information about its response. As we said in Chapter 4, "Retrieving Information", a full discussion of all the possible HTTP 1.0 and HTTP 1.1 headers is beyond the scope of this book. Table 5-2 lists the HTTP headers that are most often set by servlets as a part of a response.
The HttpServletResponse class provides a number of methods to assist servlets in setting HTTP response headers. Use setHeader() to set the value of a header:
public void HttpServletResponse.setHeader(String name, String value)
This method sets the value of the named header as a String. The name is case insensitive, as it is for all these methods. If the header had already been set, the new value overwrites the previous one. Headers of all types can be set with this method.
If you need to specify a time stamp for a header, you can use setDateHeader() :
public void HttpServletResponse.setDateHeader(String name, long date)
This method sets the value of the named header to a particular date and time. The method accepts the date value as a long that represents the number of milliseconds since the epoch (midnight, January 1, 1970 GMT). If the header has already been set, the new value overwrites the previous one.
Finally, you can use setIntHeader() to specify an integer value for a header:
public void HttpServletResponse.setIntHeader(String name, int value)
This method sets the value of the named header as an int. If the header had already been set, the new value overwrites the previous one.
The containsHeader() method provides a way to check if a header already exists:
public boolean HttpServletResponse.containsHeader(String name)
This method returns true if the named header has already been set, false if not.
In addition, the HTML 3.2 specification defines an alternate way to set header values using the <META HTTP-EQUIV> tag inside the HTML page itself:
<META HTTP-EQUIV="name" CONTENT="value">
This tag must be sent as part of the <HEAD> section of the HTML page. This technique does not provide any special benefit to servlets; it was developed for use with static documents, which do not have access to their own headers.
One of the useful things a servlet can do using status codes and headers is redirect a request. This is done by sending instructions for the client to use another URL in the response. Redirection is generally used when a document moves (to send the client to the new location), for load balancing (so one URL can distribute the load to several different machines), or for simple randomization (choosing a destination at random).
Example 5-7 shows a servlet that performs a random redirect, sending a client to a random site selected from its site list. Depending on the site list, a servlet like this could have many uses. As it stands now, it's just a jump-off point to a selection of cool servlet sites. With a site list containing advertising images, it can be used to select the next ad banner.
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class SiteSelector extends HttpServlet { Vector sites = new Vector(); Random random = new Random(); public void init(ServletConfig config) throws ServletException { super.init(config); sites.addElement("http://www.oreilly.com/catalog/jservlet"); sites.addElement("http://www.servlets.com"); sites.addElement("http://jserv.java.sun.com"); sites.addElement("http://www.servletcentral.com"); } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); int siteIndex = Math.abs(random.nextInt()) % sites.size(); String site = (String)sites.elementAt(siteIndex); res.setStatus(res.SC_MOVED_TEMPORARILY); res.setHeader("Location", site); } }
The actual redirection happens in two lines:
res.setStatus(res.SC_MOVED_TEMPORARILY); res.setHeader("Location", site);
The first line sets the status code to indicate a redirection is to take place, while the second line gives the new location. To guarantee they will work, you must call these methods before you send any output. Remember, the HTTP protocol sends status codes and headers before the content body. Also, the new site must be given as an absolute URL (for example, http://server:port/path/file.html). Anything less than that may confuse the client.
These two lines can be simplified to one using the sendRedirect() convenience method:
public void HttpServletResponse.sendRedirect(String location) throws IOException
This method redirects the response to the specified location, automatically setting the status code and Location header. For our example, the two lines become simply:
res.sendRedirect(site);
Client pull is similar to redirection, with one major difference: the browser actually displays the content from the first page and waits some specified amount of time before retrieving and displaying the content from the next page. It's called client pull because the client is responsible for pulling the content from the next page.
Why is this useful? For two reasons. First, the content from the first page can explain to the client that the requested page has moved before the next page is automatically loaded. Second, pages can be retrieved in sequence, making it possible to present a slow-motion page animation.
Client pull information is sent to the client using the Refresh HTTP header. This header's value specifies the number of seconds to display the page before pulling the next one, and it optionally includes a URL string that specifies the URL from which to pull. If no URL is given, the same URL is used. Here's a call to setHeader() that tells the client to reload this same servlet after showing its current content for three seconds:
setHeader("Refresh", "3");
And here's a call that tells the client to display Netscape's home page after the three seconds:
setHeader("Refresh", "3; URL=http://home.netscape.com");
Example 5-8 shows a servlet that uses client pull to display the current time, updated every 10 seconds.
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class ClientPull extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); res.setHeader("Refresh", "10"); out.println(new Date().toString()); } }
This is an example of a text-based animation--we'll look at graphical animations in the next chapter. Note that the Refresh header is nonrepeating. It is not a directive to load the document repeatedly. For this example, however, the Refresh header is specified on each retrieval, creating a continuous display.
The use of client pull to retrieve a second document is shown in Example 5-9. This servlet redirects requests for one host to another host, giving an explanation to the client before the redirection.
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class ClientPullMove extends HttpServlet { static final String NEW_HOST = "http://www.oreilly.com"; public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); String newLocation = NEW_HOST + req.getRequestURI(); res.setHeader("Refresh", "10; URL=" + newLocation); out.println("The requested URI has been moved to a different host.<BR>"); out.println("Its new location is " + newLocation + "<BR>"); out.println("Your browser will take you there in 10 seconds."); } }
This servlet generates the new location from the requested URI, which allows it to redirect any requests made to the old server. With the Java Web Server, this servlet could be configured to handle every request, to gradually transition clients to the new location.
Copyright © 2001 O'Reilly & Associates. All rights reserved.