To create a servlet, create a class that extends either GenericServlet or HttpServlet, overriding the appropriate methods so that the servlet handles request.
This section discusses the following topics:
To create a servlet, write a public Java class that includes basic I/O support as well as the package javax.servlet. The class must extend either GenericServlet or HttpServlet. Because Sun Java System Web Server 7.0 servlets exist in an HTTP environment, the latter class is recommended. If the servlet is part of a package, you must also declare the package name so the class loader can properly locate it.
The following example header shows the HTTP servlet declaration called MyServlet:
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class myServlet extends HttpServlet { ...servlet methods... } |
Next, override one or more methods to provide the servlet with instructions to perform its intended task. All processing by a servlet is done on a request-by-request basis and happens in the service methods, either service() for generic servlets or one of the doOperation() methods for HTTP servlets. This method accepts requests processes them according to the instructions you provide, and directs the output appropriately. You can create other methods in a servlet as well.
Override the class initializer init() to initialize or allocate resources for the servlet instance's life, such as a counter. The init() method runs after the servlet is instantiated but before it accepts any requests. For more information, see the servlet API specification.
When extending GenericServlet or HttpServlet, you must either override init(ServletConfig) to first call super.init(ServletConfig) or simply override the init() method that takes no arguments. This your servlet's ServletConfig enables be saved locally and later returned by calls to your servlet's getServletConfig() method.
The following example of the init() method initializes a counter by creating a public integer variable called thisMany:
public class myServlet extends HttpServlet { int thisMany; public void init (ServletConfig config) throws ServletException { super.init(config); thisMany = 0; } } |
This method enables other servlet methods to access the variable.
Override the class destructor destroy() to write log messages or to release resources that have been opened in the servlet's cycle. Resources should be appropriately closed and de-referenced so that they are recycled or garbage collected. The destroy() method runs just before the servlet itself is deallocated from memory. For more information, see the servlet API specification.
For example, the destroy() method could write a log message like the following example, based on the example for Overriding init():
out.println("myServlet was accessed " + thisMany " times.\\n"); |
When a request is made, Sun Java System Web Server 7.0 sends incoming data to the servlet engine to process the request. The request includes form data, cookies, session information, and URL name-value pairs, all in a type HttpServletRequest object called the request object. Client metadata is encapsulated as a type HttpServletResponse object called the response object. The servlet engine passes both objects as the servlet's service() method parameters.
The default service() method in an HTTP servlet routes the request to another method based on the HTTP transfer method (POST, and GET). For example, HTTP POST requests are routed to the doPost() method, HTTP GET requests are routed to the doGet() method. This routing enables the servlet to perform different request data processing depending on the transfer method. Because the routing takes place in service(), you do not need to override service() in an HTTP servlet. Instead, override doGet(), anddoPost() depending on the expected request type.
The automatic routing in an HTTP servlet is based on a call to request.getMethod(), which provides the HTTP transfer method.
Override the service() method for generic servlets or the doGet() or doPost() methods for HTTP servlets to perform tasks needed to answer the request. Very often, these tasks collate the needed information (in the request object or in a JDBC result set object), and then passing the newly generated content to a JSP for formatting and delivery back to the client.
Most operations that involve forms use either a GET or a POST operation, so for most servlets you override either doGet() or doPost(). Implement both methods to provide for both input types or pass the request object to a central processing method, as shown in the following example:
public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } |
All request-by-request traffic in an HTTP servlet is handled in the appropriate doOperation() method, including session management, user authentication, JSP pages, and accessing Sun Java System Web Server 7.0 features.
If a servlet calls the RequestDispatcher method include() or forward(), the request information is no longer sent as HTTP POST, and GET. In other words, if a servlet overrides doPost(), it may not process other servlets if the calling servlet happens to receive its data through HTTP GET. For this reason, be sure to implement routines for all possible input types. RequestDispatcher methods always call service().
For more information, see Calling a Servlet Programmatically.
Incoming data is encapsulated in a request object. For HTTP servlets, the request object type is HttpServletRequest. For generic servlets, the request object type is ServletRequest. The request object contains all request parameters, including custom values called attributes.
To access all incoming request parameters, use the getParameter() method, for example:
String username = request.getParameter("username"); |
Set and retrieve values in a request object using setAttribute() and getAttribute(), respectively, for example:
request.setAttribute("favoriteDwarf", "Dwalin"); |
From a Web Server's perspective, a web application is a series of unrelated server hits. No automatic recognition occurs if a user has visited the site before, even if the last interaction was seconds before. A session provides a context between multiple user interactions by remembering the application state. Clients identify themselves during each interaction by a cookie, or, in the case of a cookie-less browser, by placing the session identifier in the URL.
After a successful login, you should direct a servlet to establish the user's identity in a standard object called a session object that holds information about the current session, including the user's login name and any additional information to retain. Application components can then query the session object to obtain user authentication.
A session object can store objects, such as tabular data, information about the application's current state, and information about the current user. Objects bound to a session are available to other components that use the same session.
For more information about session objects, see Chapter 6, Session Managers.
By default, servlets are not thread-safe. The methods in a single servlet instance are usually executed numerous times simultaneously up to the available memory limit. Each execution occurs in a different thread, though only one servlet copy exists in the servlet engine.
This efficient system resource usage, is dangerous because of the way the environment Java language manages memory. Because variables belonging to the servlet class are passed by reference, different threads can overwrite the same memory space as a side effect. To make a servlet or a block within a servlet thread-safe, do one of the following:
Synchronize write access to all instance variables, as in public synchronized void method() (whole method) or synchronized(this) {...} (block only). Because synchronizing slows response time considerably, synchronize only blocks, or make sure that the blocks in the servlet do not need synchronization.
Web containers synchronize all access to their servlets only when javax.servlet.SingleThreadModel servlet is implemented.
javax.servlet.singleThreadModel is deprecated in Servlet 2.4.
For example, the following servlet has a thread-safe block in doGet() and a thread-safe method called mySafeMethod():
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class myServlet extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //pre-processing synchronized (this) { //code in this block is thread-safe } //other processing; } public synchronized int mySafeMethod (HttpServletRequest request) { //everything that happens in this method is thread-safe } } |
Use the SingleThreadModel class to create a single-threaded servlet. When a single-threaded servlet is deployed to the Sun Java System Web Server 7.0, the servlet engine creates a servlet instance pool used for incoming requests, multiple copies of the same servlet in memory. You can change the number of servlet instances in the pool by setting the singleThreadedServletPoolSize property in the Sun Java System Web Server 7.0
Web application deployment descriptor. For more information, see Chapter 9, Deploying Web Applications. Servlet performance becomes slower due to traffic load, and any new requests must wait for a free instance in order to proceed. However, with distributed, load-balanced applications, the load automatically shifts to a less busy process.
For example the following servlet is completely single-threaded:
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class myServlet extends HttpServlet implements SingleThreadModel { servlet methods... } |
If a servlet is specifically written as a single thread, the servlet engine creates a pool of servlet instances to be used for incoming requests. If a request arrives when all instances are busy, the request is queued until an instance becomes available.
The final user interaction activity is to provide a response page to the client. The response page can be delivered by creating a servlet response page or JSP response page.
Generate the output page within a servlet by writing to the output stream. The recommended generation method depends on the output type.
Always specify the output MIME type using setContentType() before any output commences, as follows
response.setContentType("text/html"); |
For textual output, such as plain HTML, create a PrintWriter object and then write to it using println, for example:
PrintWriter output = response.getWriter(); output.println("Hello, World\\n"); |
For binary output, write to the output stream directly by creating a ServletOutputStream object and then write to it using print(), for example:
ServletOutputStream output = response.getOutputStream(); output.print(binary_data); |
Servlets can invoke JSP files in two ways, the include() method and the forward() method.
The include() method in the RequestDispatcher interface calls a JSP file and waits for it to return before continuing to process the interaction. The include() method can be called multiple times within a given servlet.
This example shows a JSP file using include():
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("JSP_URI"); dispatcher.include(request, response); ... //processing continues |
The forward() method in the RequestDispatcher interface handles the JSP interaction control. The servlet is no longer involved with the current interactions output after invoking forward() therefore only one call to the forward() method can be made in a particular servlet.
You cannot use the forward() method if you have already defined a PrintWriter or ServletOutputStream object.
This example shows a JSP page using forward():
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("JSP_URI"); dispatcher.forward(request, response); |
You identify which JSP noun to call by specifying a Universal Resource Identifier (URI). The path is a String describing a path within the ServletContext scope. You can also use the getRequestDispatcher() method in the request object that takes a String argument indicating a complete path.
Identify
The getRequestDispatcher method is similar to the RequestDispatcher in the ServletContext. The servlet container uses the information in the request object to transform the given relative path to a complete current servlet path, for example:
RequestDispatcher dispatcher = req.getRequestDispatcher(“foo/bar”);
In the previous example getRequestDispatcher does not start with “/”. In Web Server 6.1, this syntax resulted in a URI such as /webapp/foo/bar. In Sun Java System Web Server 7.0, the URI appears as /webapp/current_servlet_path/foo/bar
For more information about JSP pages, see Chapter 5, Developing JavaServer Pages.