HTTP Servlets

HTTP Servlets

As we have mentioned, the javax.servlet package provides generic interfaces and classes to service clients’ requests independent of the protocol used. This means that any behavior that is specific to a particular package has to be implemented by the developer within the application. For this reason the javax.servlet package is extended to provide a mechanism to handle requests in a protocol-dependent manner. This allows protocol-specific functionality to automatically be provided to the developer.

In this section, you’ll look at one such extension: the javax.servlet.http package. This package provides classes that can be used and extended to develop servlets that provide HTTP-specific functionality. The main class in the javax.servlet.http package is the HttpServlet abstract class. This class extends from the javax.servlet.GenericServlet class. This means that all functionality provided by this class is available to HTTP servlets. The first thing to note about the HttpServlet class is that it provides several new methods that provide protocol-specific functionality. Instead of the single service() method as in the GenericServlet class, you now have methods such as doGet() and doPost() that allow your servlet to perform a different task depending upon the manner in which it’s being called. However, this very rarely happens in practice.

The request-handling methods that are provided are as follows:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                             throws ServletException, IOException

The doGet() method is intended to retrieve an entity from the server as referenced by a request URL.

    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
                                           throws ServletException, IOException

The doHead() method is simply a GET request that is intended to return only the HTTP header information.

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                                           throws ServletException, IOException

The doPost() method is intended to allow posting of information (forms and so on) to the server.

    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
                                       throws ServletException, IOException

The doPut() method is used to upload a file to a server in a manner similar to the FTP.

    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
                                           throws ServletException, IOException
    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
                                           throws ServletException, IOException

The doOptions() and doTrace() methods allow you to override the behavior of HTTP. There is almost no reason to override either of these methods unless the servlet implements functionality beyond the HTTP 1.1 specification.

To handle a request of a given type you simply override the appropriate method.

HTTP Responses and Requests

As well as providing the HttpServlet class, the javax.servlet.http package also provides HTTP-specific versions of the ServletRequest and ServletResponse objects. These are named HttpServletRequest and HttpServletResponse, respectively.

HttpServletRequest

You can use the HttpServletRequest interface to find out about the HTTP-specific information of your request to our HttpServlet (such as the HTTP request parameters). As this class extends the ServletRequest class, you can perform all of the functions of that class as well, such as retrieving request parameters, and so on. Some of the useful operations that you can perform on your request are covered in the following sections.

Retrieving HTTP Request Header Information

HTTP headers store a wide range of information about the user and the request, and they are transmitted between a user (usually a browser) and a web server during each request. HTTP header information is separate from the body of a request and provides some very useful information that can be used by a web component (servlet or JSP page) when constructing a response.

A few of the more common headers are shown here to give you an idea of the information passed between the browser and web server:

Header

Denotes

The HttpServletRequest interface provides access to the available headers using the following methods:

    public String getHeader(String name)
    public java.util.Enumeration getHeaders(String name)
    public java.util.Enumeration getHeaderNames()
    public String getMethod()

As you can see, the available methods for accessing HTTP headers take a similar form to those methods used for accessing HTML form parameters. The getHeader() method is used to access a given header’s value while the getHeaders() method returns an enumeration of string objects that represent all of the values of a given request header. This method can be used for headers that may have multiple values such as the Accept-Language header. Finally, when you are unsure of the available headers, the getHeaderNames() method may be used to obtain an enumeration of available header names. Finally, the getMethod() method can be used to retrieve the HTTP method used, such as GET, POST, or PUT.

HttpServletRequest also provides a couple of utility methods that can be used to convert the return type of specific header values:

    public long getDateHeader(String header)

The getDateHeader() method will return a given header as a long value that represents a Date object. This method could be used with the If-Modified-Since or Date headers:

    public int getIntHeader(String header)

The getIntHeader() method returns a given header as an integer value.

Both of these methods will return 1 if the given header isn’t available. The reason to use these over the alternative getHeader() method is that you won’t have to perform any casting on the value returned. This produces neater and more reliable code.

  Important

The name of the header passed to the getHeader() method isn’t case sensitive, like the majority of the HttpServletRequest methods such as getParameter().

Retrieving Path Information

You can also extract a lot of information relating to the path used to request your servlet. The following methods return information about this path:

    public String getQueryString()

The getQueryString() returns the query string of a request or null if there was no query string. For example, for the following URL, http://localhost:8080/servletExamples/TestServlet?name=sam, the method would return name=sam.

    public String getContextPath()

The getContextPath() method returns the first part of the URL after the first / after localhost:8080. For the example URL this would return servletExamples.

    public String getServletPath()

The getServletPath() returns the path to your servlet. In the URL mentioned earlier this would return /TestServlet.

    public String getPathInfo()

The getPathInfo() returns any additional path information after your servlet path and before your query string. In our example there is no such information present, so null would be returned.

    public String getRequestURI()

The getRequestURI() returns the complete URI for the request; for example, this would be /servletExamples/TestServlet?name=sam for the URL mentioned earlier.

    public String getRequestURL()

The getRequestURL() returns the full URL that the client entered into the browser to make the request to your servlet. For example, this is http://localhost:8080/servletExamples/TestServlet?name=sam, for the URL mentioned earlier (yes that is correct, it’s the whole URL!).

HttpServletResponse

You can use the HttpServletResponse interface to provide a response to the request to your servlet. Because this class extends the ServletResponse interface, you can perform all of the functions of that class as well. Some of the useful operations that you can perform on your response are covered here.

Setting an HTTP Response Header and Setting the Content Type of the Response

You’ve seen how the HttpServletRequest interface provides methods to access any HTTP headers set by a client’s browser when requesting a web resource. Similarly, the HttpServletResponse interface provides methods to set headers in the response that is sent back to the browser from the web server. These methods are as follows:

    public void addHeader(String name, String value)
    public void setDateHeader(String name, long date)
    public void addIntHeader(String name, int value)
    public void setHeader(String name, String value)
    public void setDateHeader(String name, long value)
    public void setIntHeader(String name, int value)

Here you can see two similar types of methods: the addXxxHeader() and setXxxHeader(). Although very similar in functionality, the two method types have distinctly different behavior. The addHeader(), addDateHeader(), and addIntHeader() methods all simply add a named header value to the response. The result of calling any of these three methods is that multivalue headers can be created in the response.

The setHeader(), setDateHeader(), and setIntHeader() methods will actually check for the existence of a header or headers with the same name already in the response. If the methods find an existing header or headers, they are simply replaced with the new value, otherwise a new header is created.

It’s important to note that for any headers to take effect they obviously must be set before the response is committed and sent back to the client.

The HttpServletResponse interface also inherits the following two methods from its super class javax.servlet.ServletResponse:


    public void setContentLength(int length)
    public void setContentType(String type)

The setContentLength() method, used for persistent HTTP connections, sets the length of the content body returned to the client. If this value is set too low then the client may stop reading the response prematurely. Likewise, setting this value too high may leave clients hanging around, needlessly waiting for more data. When this method is called from an HTTP servlet, it has the effect of setting the Content-Length header.

The setContentType() method is used to set the Multipurpose Internet Mail Extensions (MIME, RFC 2045 and 2046) type of the response. The effect of calling this method from an HTTP servlet is that the Content-Type header is set accordingly.

In an HTTP servlet that serves HTML content the content type is set as follows:

    response.setContentType("text/html");

text/html is the most common type of content returned from servlets. It should also be noted that MIME types are used in many protocols other than HTTP (such as SMTP e-mail) to indicate the type of the response and to show that many different content types exist.

Another method that is worth mentioning in this context is the setLocale(java.util.Locale) method that is provided by the javax.servlet.ServletResponse interface. This method automatically sets appropriate headers including the Content-Type’s charset for the appropriate locale.

Acquiring a Text Stream for the Response

The ServletResponse interface is responsible for the response that is sent back to a client after the request for some form of resource (HTML, XML, file, and so on). This interface makes a java.io.PrintWriter available to any servlet that returns text-based markup such as HTML, XML, or WML to a client.

The PrintWriter object enables character data to be sent back to the client. Therefore, the following method is provided by the ServletResponse interface:

    public java.io.PrintWriter getWriter() throws java.io.IOException
  Important

This method returns a PrintWriter object that uses the character encoding as specified in the charset property of the setContentType() method, which must be called before the getWriter() method for it to have any effect.

The ServletResponse interface also provides a flushBuffer() method, which will force any content stored in an internal buffer to be written to the client. Calling the flush() method of the PrintWriter will also have a similar effect.

Acquiring a Binary Stream for the Response

As mentioned earlier, servlets do not just have to return character data such as HTML to clients. The ServletResponse interface also provides access to a javax.servlet.ServletOutputStream object, which can be used for returning binary information such as a GIF image to a client and is obtained with the following method:

    public javax.servlet.ServletOutputStream getOutputStream() throws
                                      java.io.IOException

The ServletOutputStream, as the name suggests, is a subclass of java.io.OutputStream so the normal techniques of chaining may be employed: The ServletOutputStream is wrapped inside a java.io.BufferedOutputStream or java.io.ObjectOutputStream.

Calling flush() on the ServletOutputStream or flushBuffer() on the ServletResponse will commit the response to the client.

Redirecting an HTTP Request to another URL

It’s often desirable for a servlet to redirect the request to another URL. The reasons for doing this are many, for example a user may not have logged in to an application and needs to be redirected to a login page or a site may have moved and users need to be pointed toward an alternative URL.

As the name suggests, the redirect mechanism involves a server informing the client that they must request another URL. Most modern browsers support this functionality automatically and it causes the user only a slightly longer waiting period before their request is served.

It should be noted that there is a distinct difference between redirecting and forwarding a user to an alternative URL. Forwarding is totally invisible to the client and the resource that was forwarded to is returned as if it were the output from the original request. This is a very powerful mechanism; generally, forwarding is used to hide the implementation details of components that make up a web application.

The sendRedirect() method is provided by the javax.servlet.http.HttpServletResponse interface:

    public void sendRedirect(String location)

The location URL passed into the sendRedirect() method may be an absolute or relative URL. Absolute URLs must start with a “/” and are interpreted as relative to the servlet container root. Relative URLs do not start with a “/” and are interpreted as relative to the current request URI.

It’s important to note that if the response has already been committed when the sendRedirect() method is called, an IllegalStateException is thrown.

Another important point to note is that if URL rewriting is being used to maintain client sessions and a redirect is required, then the encodeRedirectURL() method of the HttpServletResponse interface should be used to add the session information to the redirect URL so that the client’s session state is maintained. There are multiple types of redirect headers, which are detailed in the section “Error Pages.”

HttpServlet Example

This section will look at a simple example of an HttpServlet. This servlet will simply obtain the headers from the HttpRequest and respond by outputting these to the requesting browser. Here, you do not implement duplicate functionality in both the doGet() and doPost() methods, rather you call one from the other (doPost() calls doGet()) so that the servlet responds identically if it was called by either of these methods. The code for the servlet is shown here:

    package com.apress.projsp20.ch02;

    import java.io.*;
    import java.util.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    public class HttpServletHeaders extends HttpServlet {

      public void doGet(HttpServletRequest request,
                        HttpServletResponse response)
                        throws IOException, ServletException {

        response.setContentType("text/html");

        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body bgcolor=\"white\">");
        out.println("<head>");

        out.println("<title>Here are the headers</title>");
        out.println("</head>");
        out.println("<body>");

        out.println("<h3>Headers</h3>");
        out.println("<table border=0>");
        Enumeration e = request.getHeaderNames();
        while (e.hasMoreElements()) {
          String headerName = (String)e.nextElement();
          String headerValue = request.getHeader(headerName);
          out.println("<tr><td>");
          out.println(headerName);
          out.println("</td><td>");
          out.println(headerValue);
          out.println("</td></tr>");
        }
        out.println("</table>");
      }

      public void doPost(HttpServletRequest request,
                         HttpServletResponse response)
                         throws IOException, ServletException {
        doGet(request, response);
      }
    }

You’ll deploy the servlet using the following deployment descriptor (see the section on deployment). As you can see it’s quite similar to the one you used earlier:

    <?xml version="1.0" encoding="ISO-8859-1"?>

    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"
             version="2.4">

      <servlet>
          <servlet-name>HttpServletHeaders</servlet-name>
          <servlet-class>com.apress.projsp20.ch02.HttpServletHeaders</servlet-class>
      </servlet>

      <servlet-mapping>
          <servlet-name>HttpServletHeaders</servlet-name>
          <url-pattern>/HeaderServlet</url-pattern>
      </servlet-mapping>

    </web-app>

Now compile the servlet file and copy it with the deployment descriptors into the following directory structure under Tomcat to deploy it:


deployment

You’ll see the following when making a request for http://localhost:8080/servletExamples/HeaderServlet:

jsp headers

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • Live
  • YahooMyWeb
  • Yigg

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

No comments yet.

Leave a comment

(required)

(required)