Transcript Servlets
CS6320 – Servlet
Structure and Lifecycle
L. Grewe
1
The Servlet Interface
Java provides the interface Servlet
Specific Servlets implement this interface
Whenever the Web server is asked to invoke
a specific Servlet, it activates the method
service() of an instance of this Servlet
(HTTP)
response
MyServlet
service(request,response)
(HTTP)
request
2
Example – Generic Servlet
import java.io.*;
import java.servlet.*;
public class HelloWorldServlet extends GenericServlet
{
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException{
PrintStream out = newPrintStream(res.getOutputStream());
out.println("Hello world!");
}
public String getServletInfo() {
}
return "Hello World Servlet";
}
3
Servlet Hierarchy
Servlet
service(ServletRequest,
ServletResponse)
Generic Servlet
HttpServlet
YourOwnServlet
doGet(HttpServletRequest ,
HttpServletResponse)
doPost(HttpServletRequest
HttpServletResponse)
doPut
doTrace
…
4
HTTP Request Methods
POST - application data sent in the
request body
GET - application data sent in the URL
HEAD - client sees only header of
response
PUT - place documents directly on
server
DELETE - opposite of PUT
TRACE - debugging aid
OPTIONS - list communication options
5
Class HttpServlet
Class HttpServlet handles requests and
responses of HTTP protocol
The service() method of HttpServlet checks
the request method and calls the
appropriate HttpServlet method:
doGet, doPost, doPut, doDelete, doTrace,
doOptions or doHead
This class is abstract
6
Creating a Servlet
Extend the class HTTPServlet
Implement doGet or doPost (or both)
Both methods get:
• HttpServletRequest: methods for getting form
(query) data, HTTP request headers, etc.
• HttpServletResponse: methods for setting
HTTP status codes, HTTP response headers,
and get an output stream used for sending
data to the client
Many times, we implement doPost by
calling doGet, or vice-versa
7
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
HelloWorld.java
public class TextHelloWorld extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse
res) throws ServletException, IOException {
PrintWriter out = res.getWriter();
out.println("Hello World");
}
public void doPost(HttpServletRequest req, HttpServletResponse
res) throws ServletException, IOException {
doGet(req, res);
}
}
8
The Response: Returning HTML
By default, no content type is given
with a response
In order to generate HTML
• Tell the browser you are sending HTML, by
setting the Content-Type header
• Modify the printed text to create a legal
HTML page
You should set all headers before
writing the document content. Can you
guess why?
9
HelloWorld.java
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<html><head><title>Hello World</title></head>\n");
out.println("<body>");
out.println("<h2>" + new java.util.Date() + "</h2>\n");
out.println("<h1>Hello World</h1>\n</body></html>"); }
}
10
Life of a Servlet
Birth: Create and initialize the
servlet
Important method: init()
Life: Handle 0 or more client
requests
Important methods: service(), doGet(),
and doPost().
Death: Destroy the servlet
Important method: destroy()
11
Servlet Life Cycle
Calling the
init method
Servlet
Instance
Servlet Class
Deal with requests:
call the
service method
Destroy the Servlet:
call the
destroy method
ServletConfig
Garbage
Collection
12
The init() method
The init() method is called when the servlet
is first requested by a browser request.
It is not called again for each request.
Used for one-time initialization.
The method init is overloaded and has a
parameter of type ServletConfig
ServletConfig has methods to get external
initialization parameters
• In Tomcat, these parameters are set in web.xml
To make initializations, override init() and not
init(ServletConfig)
• init() is automatically called by after performing
13
default initializations
Service() Method
Each time the server receives a request for a
servlet, the server spawns a new thread and calls
the servlet’s service () method.
Browser
Browser
service()
Web Server
service()
service()
Single Instance
of Servlet
Browser
14
The Service Method
By default the service() method checks
the HTTP Header.
Based on the header, service calls either
doPost() or doGet().
doPost and doGet is where you put the
majority of your code.
If your servlets needs to handle both get
and post identically, have your doPost()
method call doGet() or vice versa.
15
Thread Synchronization
By default, multiple threads are accessing
the same servlet object at the same time.
You therefore need to be careful to
synchronize access to shared data.
For example, the code on the next slide
has a problem…
16
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
This code is problematic.
Can result in a race condition,
where two users can actually
get the same User-ID!
For example:
public class UserIDs extends HttpServlet {
private int nextID = 0;
public void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Your ID";
String docType = …
String id = "User-ID-" + nextID;
out.println("<H2>" + id + "</H2>");
nextID = nextID + 1;
out.println("</BODY></HTML>");
}
}
User 1 makes request:
String id = "User-ID-" + nextID;
Gets nextId of 45.
Now User 2 makes request,
and pre-empts user 1:
String id = "User-ID-" + nextID;
Gets nextId of 45 (same one!)
Admittedly, this case is rare,
but it’s especially problematic.
Imagine if user Id was tied to
credit card number!
17
How to Solve Synchronization Problems
You have a few options for solving
servlet synchronization issues:
1) Never use instance variables (or protect
them) in your servlets…use local variables. If
you don’t have shared instance variables,
you don’t have shared synchronization
problems.
2) Synchronize code explicitly with Java
synchronization blocks.
3) Note recommended - Use the
SingleThreadInterface
18
Java Synchronization
Use a synchronization block whenever
accessing/modifying a shared variable.
For example:
synchronized (this) {
String id = "User-ID-" + nextID;
out.println("<H2>" + id + "</H2>");
nextID = nextID + 1;
}
19
SingleThreadModel Interface
To prevent multi-threaded access, you can have your
servlet implement the SingleThreadModel:
public class YourServlet extends HttpServlet implements
SingleThreadModel {
…
}
This will guarantee that your servlet will only process one
browser request at a time.
It therefore addresses most synchronization issues.
Unfortunately, however, it can result in severe slowing of
performance, and most people strongly recommend against
using it.
In fact, the SingleThreadModel interface is now deprecated
in the Servlet 2.4 API.
20
Death of a Servlet
Before a server shuts down, it will call the
servlet’s destroy() method.
You can handle any servlet clean up here. For
example:
Updating log files.
Closing database connections.
Closing any socket connections.
The server may remove a loaded Servlet, Why?:
• asked to do so by administrator(e.g. Server shutdown)
• Servlet was idle a long time
• server needs to free resources
The server removes a Servlet only if all threads
have finished or a grace period has passed
21
Example: Persistent Counter
To create a persistent record, we can
store the count value within a
“counter.txt” file.
init(): Upon start-up, read in the
current counter value from counter.txt.
destroy(): Upon destruction, write out
the new counter value to counter.txt
22
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CounterPersist extends HttpServlet {
String fileName = "counter.txt";
int count;
At Start-up, load the
counter from file.
In the event of any
exception, initialize
count to 0.
public void init () {
try {
FileReader fileReader = new FileReader (fileName);
BufferedReader bufferedReader = new BufferedReader (fileReader);
String initial = bufferedReader.readLine();
count = Integer.parseInt (initial);
} catch (FileNotFoundException e) { count = 0; }
catch (IOException e) { count = 0; }
catch (NumberFormatException e) { count = 0; }
Continued….
}
23
// Handle an HTTP GET Request
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
count++;
out.println ("Since loading, this servlet has "
+"been accessed "+ count + " times.");
out.close();
}
Each time the
doGet() method is
called, increment the
count variable.
Continued….
24
}
}
// At Shutdown, store counter back to file
public void destroy() {
try {
FileWriter fileWriter = new FileWriter (fileName);
String countStr = Integer.toString (count);
fileWriter.write (countStr);
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
When destroy() is
Any problems with
this code?
called, store new
counter variable back
to counter.txt.
25