《Java Servlet Programming》读书笔记_2010.06.14

2010-06-14

5.6 Http Headers

       HTTP Response Headers

Header

Usage

Cache-Control

Specifies any special treatment a caching system should give to this document. The most common values are no-cache (to indicate this document should not be cached), no-store (to indicate this document should not be cached or even stored by a proxy server, usually due to its sensitive contents), and max-age=seconds (to indicate how long before the document should be considered stale). This header was introduced in HTTP 1.1.[1]

Pragma

This is the HTTP 1.0 equivalent of Cache-Control, with no-cache as its only possible value. It's wise to use Pragma in conjunction with Cache-Control to support older browsers.

Connection

Used to indicate whether the server is willing to maintain an open (persistent) connection to the client. If so, its value is set to keep-alive. If not, its value is set to close. Most web servers handle this header on behalf of their servlets, automatically setting its value to keep-alive when a servlet sets its Content-Length header or when the server can automatically determine the content length.

Retry-After

Specifies a time when the server can again handle requests, used with the SC_SERVICE_UNAVAILABLE status code. Its value is either an int that represents the number of seconds or a date string that represents an actual time.

Expires

Specifies a time when the document may change or when its information will become invalid. It implies that it is unlikely the document will change before that time.

Location

Specifies a new location of a document, usually used with the status codes SC_CREATED, SC_MOVED_PERMANENTLY, and SC_MOVED_TEMPORARILY. Its value must be an fully qualified URL (including http://).

WWW-Authenticate

Specifies the authorization scheme and the realm of authorization required by the client to access the requested URL. Used with the status code SC_UNAUTHORIZED.

Content-Encoding

Specifies the scheme used to encode the response body. Example values are gzip (or x-gzip) and compress (or x-compress). Multiple encodings should be represented as a comma-separated list in the order in which the encodings were applied to the data.

      

       Setting an HTTP Header

l  public void HttpServletResponse.setHeader(String name, String value)

n  This method sets the value of the named header as a String.

n  The name is case insensitive, as it is for all these methods.

n  If the header had already been set, the new value overwrites the previous one.

n  Headers of all types can be set with this method.

l  public void HttpServletResponse.setDateHeader(String name, long date)

n  This method sets the value of the named header to a particular date and time.

n  The method accepts the date value as a long that represents the number of milliseconds since the epoch(midnight, January 1, 1970, GMT)

l  public void HttpServletResponse.setIntHeader(String name, int value)

n  sets the value of the named header as an int

l  public Boolean HttpServletResponse,containsHeader(String name)

n  provides a way to check if a header already exists

n  returns true if the named header has already been set, false if not

l  when a servlet has to send multiple values for the same header

n  public void HttpServletResponse.addHeader(String name, String value)

n  public void HttpServletResponse.addDateHeader(String name, long value)

n  public void HttpServletResponse.addIntHeader(String name, int value)

 

Redirecting a Request

l  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.

l  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() throws ServletException {
    sites.addElement("http://www.oreilly.com/catalog/jservlet2");
    sites.addElement("http://www.servlets.com");
    sites.addElement("http://java.sun.com/products/servlet");
    sites.addElement("http://www.newInstance.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);
  }
}
    
               
l  res.setStatus(res.SC_MOVED_TEMPORARILY);
          res.setHeader("Location", site);

These two lines can be simplified to one using the sendRedirect( ) convenience method:

            public void HttpServletResponse.sendRedirect(String location) 
            throws IOException, IllegalStateException
n  This method performs an implicit reset on the response buffer before generating the redirect page. Headers set before sendRedirect( ) remain set.
 
Watching Lingks to Other Sites
l  A servlet can be registered to handle the /goto/* path prefix where it will receive the selected URL as extra path info and redirect the client to that location after making a note in the server log.
 
Client Pull
l  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.

l  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.

l  Client pull information is sent to the client using the Refresh HTTP header.
l  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.
l  Example:setHeader("Refresh", "3; URL=http://home.netscape.com");
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());
  }
}
       
       5.7 When Things Go Wrong
l  There are two points of concern when things go wrong:
n  Limiting damage to the server
n  Properly informing the client
l  Java's security manager mechanism provides a way for servers to place untrusted servlets in a sandbox, limiting their abilities and keeping them from intentionally causing problems.

l  How much to tell the client?

l  How to record the problem?

n  Should it be saved to a file, written to the server log, sent to the client, or ignored?

l  How to recover?

n  Can the same servlet instance handle subsequent requests? Or is the servlet corrupted, meaning that it needs to be reloaded?

 
Status Codes
l  The simplest (and arguably best) way for a servlet to report an error is to use the sendError( ) method to set the appropriate 400 series or 500 series status code.

n  If the error is such that a servlet ought to provide its own explanation to the client in the response body, it can set the status code with setStatus( ) and send the appropriate body—which could be text based, a generated image, or whatever is appropriate.

 
SConfiguring Error Pages
l  a better approach is to set up an <error-page> rule in the web.xml deployment descriptor.
<?xml version="1.0" encoding="ISO-8859-1"?>
 
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
 
<web-app>
    <!-- ..... -->
    <error-page>
        <error-code>
            400
        </error-code>
        <location>
            /400.html
        </location>
    </error-page>
    <error-page>
        <error-code>
            404
        </error-code>
        <location>
            /404.html
        </location>
    </error-page>
</web-app>
l  Servers are required to respect the <error-page> rules for all content served from the web application, even static files.
l  the value of the <location> must begin with a slash, is treated as based in the context root, and must refer to a resource within the context.
l  To reference a resource outside the current context, you can point to an HTML file within the context that contains an immediate redirect outside the context:
n  <META HTTP-EQUIV="Refresh" CONTENT="0; URL=http://www.errors.com/404.html">

l  The <location> target can be a dynamic resource, such as a servlet or JSP. For dynamic resources the server makes available two special request attributes telling information about the error:

n  javax.servlet.error.status_code

n  An Integer telling the error status code. The type was initially unspecified and some early server implementations may return the code as a String.

n  javax.servlet.error.message

n  A String telling the status message, generally passed as the second argument to sendError( ).

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class ErrorDisplay extends HttpServlet {
 
  public void doGet(HttpServletRequest req, HttpServletResponse res)
                               throws ServletException, IOException {
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
 
    Object codeObj = req.getAttribute("javax.servlet.error.status_code");
    Object messageObj = req.getAttribute("javax.servlet.error.message");
 
    // The code and message should never be null on API 2.2 compliant servers
    String code = (codeObj != null ? 
                   codeObj.toString() : "Missing Status Code");
    String message = (messageObj != null ?
                      messageObj.toString() : "Missing Error Message");
 
    out.println("<HTML>");
    out.println("<HEAD><TITLE>" + code + ": " + message + "</TITLE></HEAD>");
    out.println("<BODY>");
    out.println("<H1>" + code + "</H1>");
    out.println("<H2>" + message + "</H2>");
    out.println("<HR>");
    out.println("<I>Error accessing " + req.getRequestURI() + "</I>");
    out.println("</BODY></HTML>");
  }
}
l  An advanced version of this servlet could generate a more interesting page and could track the error codes being generated to detect odd trends, such as an abundance of 404 errors for the same URI, probably indicating a newly posted bad link somewhere that should be fixed.
l  The setStatus( ) method allows you to set an error status code and retain full control of the response.
l  The sendError( ) method lets you set an error status code and pass control of page creation to the server.

l  By default the server will send its standard error page for that code. With an <error-page> entry you can tell the server to send a special error page.

 
 
 
Logging

l  Servlets have the ability to write their actions and their errors to a log file using the log( ) method:

n  public void GenericServlet.log(String msg)
n  public void GenericServlet.log(String msg, Throwable t)
n  The single-argument method writes the given message to a servlet log, which is usually an event log file. The two-argument version writes the given message and the Throwable's stack trace to a servlet log. The exact output format and location of the log are server-specific but generally include a timestamp and the registered name of the servlet.

l  The log( ) method aids debugging by providing a way to track a servlet's actions. It also offers a way to save a complete description of any errors encountered by the servlet. The description can be the same as the one given to the client, or it can be more exhaustive and detailed.

// Return the file
try {
  ServletUtils.returnFile(file, out);
}
catch (FileNotFoundException e) {
  log("Could not find file: " + e.getMessage());
  res.sendError(res.SC_NOT_FOUND);
}
catch (IOException e) {
  log("Problem sending file", e);
  res.sendError(res.SC_INTERNAL_SERVER_ERROR);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值