8.1 HTTP Answer Header overview
HTTP responses to a Web server generally consist of a status line, one or more answer headers, a blank line, and a content document. Setting the HTTP answer headers is often combined with the status code in the Set status line. For example, there are several status codes that indicate "document location has changed" accompanied by a location header, while the 401 (unauthorized) status code must be accompanied by a www-authenticate header.
However, it is also useful to specify an answer header even when there is no state code to set a special meaning. The answer headers can be used to complete: set cookies, specify modification dates, instruct the browser to refresh the page at specified intervals, declare the length of the document to take advantage of persistent HTTP connections, ... and many other tasks.
The most common method for setting up an answer head is the HttpServletResponse SetHeader, which has two parameters, representing the name and value of the answer header, respectively. Similar to setting the status code, the answer header should be set before any document content is sent.
The Setdateheader method and the Setintheadr method are specifically used to set up an answer header that contains a date and an integer value that avoids the hassle of converting Java time to GMT time strings, and the latter avoids the hassle of converting integers to strings.
HttpServletResponse also provides a number of easy ways to set common answer headers, as follows:
setContentType: Set Content-type header. This method is used by most servlet.
Setcontentlength: Set Content-length header. This function is useful for browsers that support persistent HTTP connections.
Addcookie: Set a cookie (there is no Setcookie method in the Servlet API because the answer often contains multiple Set-cookie headers).
Also, as described in the previous section, the Sendredirect method sets the location header when the status code is set to 302.
8.2 Common answer headers and their implications
For a detailed and complete description of the HTTP headers, see the http://www.w3.org/Protocols/specification.
Answer Header Description
The Allow server supports which request methods (such as Get, post, and so on).
The encoding (Encode) method of the Content-encoding document. The content type specified by the Content-type header can be obtained only after decoding. Using gzip compressed documents can significantly reduce the download time for HTML documents. Java Gzipoutputstream can be easily gzip compressed, but only Netscape on Unix and IE 4, IE 5 on Windows support it. Therefore, the servlet should check to see if the browser supports gzip by looking at the accept-encoding header (that is, Request.getheader ("accept-encoding"). Returns a gzip-compressed HTML page for a browser that supports GZIP, returning to a normal page for another browser.
Content-length represents the length of the content. This data is required only if the browser is using persistent HTTP connections. If you want to take advantage of a persistent connection, you can write the output document to Bytearrayoutputstram, view its size after it is finished, and then put the value into the Content-length header, and finally pass Bytearraystream.writeto ( Response.getoutputstream () sends the content.
Content-type indicates what MIME type the following document belongs to. The servlet defaults to Text/plain, but usually needs to be explicitly specified as text/html. Because of the constant need to set up Content-type, HttpServletResponse provides a dedicated method Setcontenttyep.
Date's current GMT time. You can use Setdateheader to set this header to avoid the hassle of converting the time format.
When should Expires think that the document has expired so that it does not cache it?
Last-modified The last change time for the document. The customer can provide a date through the If-modified-since request header, which is treated as a condition get, and a 304 (not Modified) state is returned only if the document that was modified later than the specified time is returned. Last-modified can also be set using the Setdateheader method.
Location indicates where the customer should go to extract the document. Location is not usually set directly, but through the HttpServletResponse Sendredirect method, which sets the status code to 302.
Refresh indicates how much time the browser should refresh the document, in seconds. In addition to refreshing the current document, you can also pass SetHeader ("Refresh", "5; Url=http://host/path ") lets the browser read the specified page.
Note that this function is usually done by setting the HTML page Head area of <meta http-equiv= "Refresh" content= 5; Url=http://host/path "> This is because automatic refresh or redirection is important for HTML writers who cannot use a CGI or servlet. However, it is more convenient for the servlet to set the refresh header directly.
Note that the meaning of refresh is "refresh this page or access the specified page after n seconds" instead of "refreshing this page or accessing the specified page every n seconds." Therefore, continuous refresh requires a refresh header to be sent each time, and sending a 204 status code can prevent the browser from continuing to refresh, whether using the refresh header or <meta http-equiv= "Refresh" ... >
Note that the refresh header is not part of the HTTP 1.1 formal specification, but is an extension, but Netscape and IE support it.
Server name. The servlet typically does not set this value, but is set by the Web server itself.
Set-cookie settings and page associated cookies. The servlet should not use Response.setheader ("Set-cookie", ...), but should use the specialized method provided by HttpServletResponse Addcookie. See below for a discussion of cookie settings.
What type of licensing information should the Www-authenticate customer provide in the authorization header? This header is required in an answer that contains a 401 (unauthorized) status line. For example, Response.setheader ("Www-authenticate", "BASIC realm=\" executives\ ").
Note that the servlet typically does not do this, but instead gives the Web server a special mechanism to control access to the password-protected page (for example,. htaccess).
8.3 instance: Automatically refresh page when content changes
The following servlet is used to compute large primes. Because calculating very large numbers (for example, 500 bits) can take a long time, the servlet will immediately return the results that have been found and continue the calculation in the background. Background computing uses a lower-priority thread to avoid excessive impact on the performance of the Web server. If the calculation is not completed, the servlet instructs the browser to continue requesting new content after a few seconds by sending a refresh header.
Note that this example shows the other two valuable features of the servlet, in addition to the usefulness of the HTTP answer header. First, it shows that the servlet can handle multiple concurrent connections, each with its own thread. The servlet maintains a vector table of existing prime numbers to compute requests, matching the current request to the existing request by looking up the number of primes (the length of the list of primes) and the number of digits (the length of each prime), and synchronizing all these requests to the list. Second, this example proves that it is very easy to maintain state information between requests in the servlet. Maintaining state information is a hassle in traditional CGI programming. Because state information is maintained, the browser is able to access the ongoing calculation while refreshing the page, while also enabling the servlet to save a list of the results of the most recent request that can be returned immediately when a new request specifies the same parameters as the most recent request.
Primenumbers.java
Note that the servlet uses the Servletutilities.java given earlier. Also used: Primelist.java, to create a vector;primes.java of prime numbers in a background thread, to randomly generate large digits of BigInteger type, to check whether they are primes. (The code for Primelist.java and Primes.java is omitted here.) )
Package Hall;
Import java.io.*;
Import javax.servlet.*;
Import javax.servlet.http.*;
Import java.util.*;
public class Primenumbers extends HttpServlet {
private static vector primelistvector = new vector ();
private static int maxprimelists = 30;
public void doget (HttpServletRequest request,
HttpServletResponse response)
Throws Servletexception, IOException {
int numprimes = Servletutilities.getintparameter (Request, "Numprimes", 50);
int numdigits = Servletutilities.getintparameter (Request, "Numdigits", 120);
Primelist primelist = findprimelist (Primelistvector, Numprimes, numdigits);
if (primelist = = null) {
Primelist = new Primelist (Numprimes, Numdigits, true);
Synchronized (primelistvector) {
if (Primelistvector.size () >= maxprimelists)
Primelistvector.removeelementat (0);
Primelistvector.addelement (primelist);
}
}
Vector currentprimes = Primelist.getprimes ();
int numcurrentprimes = Currentprimes.size ();
int numprimesremaining = (numprimes-numcurrentprimes);
Boolean Islastresult = (numprimesremaining = = 0);
if (!islastresult) {
Response.setheader ("Refresh", "5");
}
Response.setcontenttype ("text/html");
PrintWriter out = Response.getwriter ();
String title = "Some" + numdigits + "-digit Prime Numbers";
Out.println (title) + Servletutilities.headwithtitle
"<body bgcolor=\" #FDF5E6 \ ">\n" +
"
""or more digits:" + Numcurrentprimes + ". if (Islastresult)
Out.println ("<B> done searching. </B>");
Else
Out.println ("<B> still looking for" + numprimesremaining +
"More <BLINK> ... </BLINK> </B>);
Out.println ("<OL>");
for (int i=0; i<numcurrentprimes; i++) {
Out.println ("<LI>" + currentprimes.elementat (i));
}
Out.println ("</OL>");
Out.println ("</BODY> </HTML>");
}
public void DoPost (HttpServletRequest request,
HttpServletResponse response)
Throws Servletexception, IOException {
Doget (request, response);
}
Check for the existence of the same type of request (completed, or being evaluated).
If present, the existing result is returned instead of starting a new background thread.
Private Primelist findprimelist (Vector primelistvector,
int Numprimes,
int numdigits) {
Synchronized (primelistvector) {
for (int i=0; i<primelistvector.size (); i++) {
Primelist primes = (primelist) primelistvector.elementat (i);
if ((Numprimes = = Primes.numprimes ()) &&
(Numdigits = = Primes.numdigits ()))
return (primes);
}
return (NULL);
}
}
}
Primenumbers.html
! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 transitional//en"
<HTML>
<HEAD>
<TITLE> Large prime number calculation </TITLE>
</HEAD>
<CENTER>
<body bgcolor= "#FDF5E6" >
<form action= "/servlet/hall. Primenumbers ">
<B> to calculate several primes: </B>
<input type= "TEXT" name= "Numprimes" value=25 size=4> <BR>
<B> the number of digits per prime: </B>
<input type= "TEXT" name= "numdigits" value=150 size=3> <BR>
<input type= "SUBMIT" value= "Start calculation" >
</FORM>
</CENTER>
</BODY>
</HTML>