Coding an HttpServlet
Previously, it has been shown that Servlets have a three-part life cycle: initialization, service, and destruction. An HttpServlet object shares this life cycle but makes a few modifications for the HTTP protocol. The HttpServlet object's implementation of the service() method, which is called during each service request, calls one of seven different helper methods. These seven methods correspond directly to the seven HTTP methods and are named as follows: doGet(), doPost(), doPut(), doHead(), doOptions(), doDelete(), and doTrace(). The appropriate helper method is invoked to match the type of method on a given HTTP request. The HttpServlet life cycle can be illustrated as shown in Figure 2-5.
Figure 2-5. HttpServlet Life Cycle
While all seven methods are shown, remember that normally only one of them is called on a given request. More than one might be called if a developer overrides the methods and has them call each other. The initialization and destruction stages of the Servlet life cycle are the same as described before.
Coding an HttpServlet is straightforward. The javax.servlet.http.HttpServlet class takes care of handling the redundant parts of an HTTP request and response, and requires a developer only to override methods that need to be customized. Manipulation of a given request and response is done through two objects, javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse. Both of these objects are passed as parameters when invoking the HTTP service methods.
It is time to step through coding and using a basic Servlet. A basic "Hello World" Servlet is appropriate for getting started (see Listing 2-1). Take the following code and save it as HelloWorld.java in the /WEB-INF/classes/com/jspbook directory of the jspbook Web Application.
Listing 2-1. HelloWorld.java
package com.jspbook; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld 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("<head>"); out.println("<title>Hello World!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("</body>"); out.println("</html>"); } }
You can probably see exactly what the preceding code is doing. If not, do not worry about understanding everything just yet since we have not learned how to deploy a Servlet for use which has to come before dissecting the code. For now understand that the preceding is the complete code for an HttpServlet. Once deployed, this example Servlet will generate a simple HTML page that says "Hello World!".
Deploying a Servlet
By itself a Servlet is not a full Java application. Servlets rely on being part of a Web Application that a container manages. Using a Servlet to generate dynamic responses involves both creating the Servlet and deploying the Servlet for use in the Web Application.
Deploying a Servlet is not difficult, but it is not as intuitive as you might think. Unlike a static resource, a Servlet is not simply placed in the root directory of the Web Application. A Servlet class file goes in the /WEB-INF/classes directory of the application with all the other Java classes. For a client to access a Servlet, a unique URL, or set of URLs, needs to be declared in the Web Application Deployment Descriptor. The web.xml deployment description relies on new elements14: servlet and servlet-mapping need to be introduced for use in web.xml. The servlet element is used to define a Servlet that should be loaded by a Web Application. The servlet-mapping element is used to map a Servlet to a given URL or set of URLs. Multiple tags using either of these elements can appear to define as many Servlets and Servlet mappings as needed. Both of these elements also have sub-elements used to further describe them. These sub-elements are self-descriptive, and they are introduced by use in an upcoming example.
Open up the /WEB-INF/web.xml file of the jspbook Web Application and edit it to match Listing 2-2.
Listing 2-2. Deploying HelloWorld Servlet
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"> <servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.jspbook.HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/HelloWorld</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>welcome.html</welcome-file> </welcome-file-list> </web-app>
Highlighted is the new addition to web.xml. In the highlight, notice that both an instance of the servlet and servlet-mapping element is used. In general this is how every Servlet is deployed. A Servlet is first declared by a servlet element that both names the Servlet and gives the location of the appropriate Java class. After declaration, the Servlet can be referenced by the previously given name and mapped to a URL path. The name and class values are assigned by a given string in the servlet-name and servlet-class tags, respectively. The Servlet's name is arbitrary, but it must be unique from any other Servlet name for that Web Application. In the body of the servlet-mapping tag, the name and URL path for a Servlet are given by a string value in the body of the servlet-name and url-pattern tags, respectively. The name must match a name previously defined by a servlet element. The URL path can be anything as defined by the Servlet specification:
-
An exact pattern to match. The pattern must start with a /, but can contain anything afterwards. This type of pattern is used for a one-to-one mapping of a request to a specific Servlet.
-
An extension match, *.extension. In this case all URLs ending with the given extension are forwarded to the specified Servlet. This is commonly used in Servlet frameworks and can force many requests to go to the same Servlet15.
-
A path mapping. Path mappings must start with a / and end with a /*. In between anything can appear. Path mappings are usually used for forwarding all requests that fall in a certain directory to a specific Servlet.
-
Default Servlet, /. A default Servlet mapping is used to define a Servlet for forwarding requests when no path information is given. This is analogous to a directory listing16.
With the HelloWorld Servlet, an exact pattern match was used that forwards any request for /HelloWorld directly to the Servlet (see Figure 2-6). Translating any of these URL patterns to a full URL involves prefixing the pattern with the URL to the Web Application. For the HelloWorld Servlet in the jspbook Web Application, this would be http://127.0.0.1/jspbook/HelloWorld. Restart Tomcat to update your changes and use this URL to browse to the HelloWorld Servlet17. A simple HTML page should be displayed that says "Hello World!". For non-English readers, our apologies; internationalizing this properly would require chapter precedence of 1, 12, then 2.
Figure 2-6. HelloWorld Servlet
Understand Servlet Deployment!
Deploying a Servlet is relatively simple but very important. Pay attention in the preceding example because for brevity further examples do not include the verbose deployment description. A single sentence such as "Deploy Servlet x to the URL mapping y". is used to mean the same thing. Only when it is exceptionally important to the example is the full deployment descriptor provided.
Web Application Deployment Descriptor Structure
Each and every Servlet needs to be deployed before it is available for a client to use. The HelloWorld Servlet example introduced the Web Application Deployment Descriptor elements that do this, but before you go on deploying more Servlets, there is some more information to be aware of. The schema for web.xml defines which elements can be used and in what order they must appear. In the previous example this is the reason that both the servlet and servlet-mapping elements appeared before the welcome-file-list element. This is also the reason that the servlet element was required to appear before the servlet-mapping element18.
From the preceding three elements it might seem arrangement is of alphabetical precedence, but this is not the case. The arrangement of elements must match the given listing with the Web Application Deployment Descriptor schema. This rather long title should sound familiarit is the same XML schema that defines what can appear in web.xml. The current complete schema can be found in the Servlet 2.4 specification. The element ordering is defined by the root web-inf element and is, in ascending order, as follows: icon, display-name, description, distributable, context-param, filter, filter-mapping, listener, servlet, servlet-mapping, session-config, mime-mapping, welcome-file-list, error-page, jsp-config, resource-env-ref, message-destination-ref, resource-ref, security-constraint, login-config, security-role, env-entry, ejb-ref, ejb-local-ref., message-destination, and locale-encoding-mapping-list.
Understanding the order is not difficult, but it is a problem quite a few new Servlet developers ask about. It is well worth mentioning it now to avoid causing any confusion later. Keep in mind that this order also applies to multiple elements of the same name. If two Servlets are deployed, both of the servlet elements must be listed before any of the servlet-mapping elements. It does not matter what order a group of the same elements are in, but it does matter that they are properly grouped.