When a server has client's data to compute - a CGI program, usually written in C-like or Perl languages, is executed. A CGI receives parameters, executes one or more computations, gets a result, send it back to the client and exits. This means that at each client's request the same CGI program has to be loaded, executed and terminated. This procedure is actually the most popular in the client-server environment, but it often overloads servers.
Servlets are Java applications that can perform the same work of a CGI program. Their fast diffusion means they can be considered a valid alternative. Advantages offered by servlets have to be searched first of all in the Java Servlet API (Application Program Interface) that assures programmers they can write totally portable software according to the Java principle "Write Once Run Anywhere". Moreover Java application development is easier than C or Perl one, so it easier to create a Java error free application. All these advantages are obtained to the detriment of a longer execution time. To solve this problem JSDK developers decided to have servlet loaded and initialized just once in all their life cycle. According to this strategy, a servlet is loaded at the first execution and then it is ready to run again without reloading. A servlet life cycle ends only when a particular method is invoked.
JDK 6 Documentation
Java Platform,
Standard Edition 6 API Specification
Java Platform
Enterprise Edition, v 5.0 API Specifications
Servlet
Examples with Code
<FORM method="POST" action="subscribe.cgi"> <INPUT type=hidden name="userrequest" value="subsingle"> <INPUT type=hidden name="outputfile" value="suboutput"> <INPUT type=hidden name="errorfile" value="suberror"> <TABLE cols="3"> <TR> <TD align="right"> Your E-mail Address: </TD> <TD> <INPUT type="text" name="email"> </TD> <TD align="left"> <INPUT type="submit" value="Subscribe"> </TD> </TR> </TABLE> </FORM>
General format of a request message
General format of response message
GET /java/index.html HTTP/1.0 Referer: http://sorcer.cs.ttu.edu/subscribe.html Connection: Keep-Alive User-Agent: Mozilla/4.7 [en] (Win2K; I) Host: sorcer.cs.ttu.edu Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */* Accept-Encoding: gzip Accept-Language: en Accept-Charset: iso-8859-1,*,utf-8
POST /subscribe.cgi HTTP/1.0 Referer: http://sorcer.cs.ttu.edu/subscribe.html Connection: Keep-Alive User-Agent: Mozilla/4.7 [en] (Win2K; I) Host: sorcer.cs.ttu.edu Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */* Accept-Encoding: gzip Accept-Language: en Accept-Charset: iso-8859-1,*,utf-8 Content-type: application/x-www-form-urlencoded Content-length: 85 userrequest=subsingle&outputfile=suboutput&errorfile=suberror&email=sobol%40cs.ttu.edu
GET /subscribe.cgi?userrequest=subsingle&outputfile=suboutput (cont...) &errorfile=suberror&email=sobol%40cs.ttu.edu HTTP/1.0 Referer: http://sorcer.cs.ttu.edu/subscribeNoPost.html Connection: Keep-Alive User-Agent: Mozilla/4.7 [en] (Win2K; I) Host: sorcer.cs.ttu.edu Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */* Accept-Encoding: gzip Accept-Language: en Accept-Charset: iso-8859-1,*,utf-8
"CGI" stands for "Common Gateway Interface." CGI is the method by which a web server can obtain data from (or send data to) databases, documents, and other programs, and present that data to viewers via the web. More simply, CGI is programming for the web. A CGI can be written in any programming language.
QUERY_STRING
#!/usr/local/bin/perl $mailprogram = "/usr/lib/sendmail"; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } $outputtemplate = "$FORM{'outputfile'}.html"; $errortemplate = "$FORM{'errorfile'}.html"; $mailthis = "To: [email protected]\n"; # make sure the user entered a valid email address. $temp = $FORM{'email'}; $temp =~ s/_/a/g; $temp =~ s/-/a/g; unless ($temp =~ /\w+@\w+\.\w\w+/) { &error($FORM{'email'}); exit; } $mailthis .= "From: $FORM{'email'}\n"; $mailthis .= $FORM{'userrequest'}; open(MAIL,"|$mailprogram -t"); print MAIL "$mailthis\n"; close(MAIL); &write_output_html($FORM{'email'}); exit; sub write_output_html { $email_address = $_[0]; open(OUTPUTTEMPLATE,"$outputtemplate") || die $!; print "Content-type: text/html\n\n"; while ($line =) { $line =~ s/\?email_address\?/$email_address/g; print $line; } close(OUTPUTTEMPLATE); } sub error { $email_address = $_[0]; open(ERRORTEMPLATE,"$errortemplate") || die $!; print "Content-type: text/html\n\n"; while ($line =) { $line =~ s/\?email_address\?/$email_address/g; print $line; } close(ERRORTEMPLATE); exit; }
<HTML> <HEAD> <TITLE>Subscribe to the SORCER Newsletter</TITLE> <META NAME="description" content="The SORCER Newsletter is a monthly email publication announcing the lab activities."> <META NAME="keywords" content="SORCER Newsletter, Mailing List"> </HEAD> <!--BEGIN_TITLE_BLOCK--> <font face="arial, helvetica" COLOR="#000066"> <font size=6> <SPAN class=pagetitle1>Subscription Successful</SPAN> </font> </font> <!--END_TITLE_BLOCK--> <HR align="left" width="85%"> <P> You have been successfully added to the SORCER Newsletter's mailing list at the following e-mail address: <BLOCKQUOTE> <STRONG>?email_address?</STRONG> </BLOCKQUOTE> <P>If you change your mind, you can <A href="http://www.sorcer.com/unsubscribe.html">unsubscribe</A> at any time. </BODY> </HTML>
PHP is a server-side scripting language that can be used on a host of webservers and platforms. What server-side scripting language means is that the script is put into the HTML files that make up a site, but the server processes the script BEFORE it is sent to the client browser. PHP code is not visible if you view the source of a page because the server processes the code and returns only the output. This is easier to code and debug than writing CGI scripts in Perl or C since the HTML form and related code are all in one page and PHP puts any errors on the browser.
Another advantage that PHP offers is the ability to directly connect to relational databases using full featured internal functions. It supports a whole fleet of databases including Oracle, DB2, mSQL and MySQL.
The PHP code stars with the <?php" tag and ends at "?> tag.
Servlets are modules of Java code that run in a server application (hence the name "Servlets", similar to "Applets" on the client side) to answer client requests. Servlets are not tied to a specific client-server protocol but they are most commonly used with HTTP and the word "Servlet" is often used in the meaning of "HTTP Servlet".
Servlets make use of the Java standard extension classes in the packages
javax.servlet
(the basic Servlet framework) and
javax.servlet.http
(extensions of the Servlet framework for Servlets that
answer HTTP requests). Since Servlets are written in the highly portable Java
language and follow a standard framework, they provide a means to create
sophisticated server extensions in a server and operating system independent
way.
Typical uses for HTTP Servlets include:
Servlets have several advantages over CGI:
In Java 2 Platform, Enterprise Edition (J2EE) v1.4, JSP technology has simplified the page and extension development models with the introduction of a simple expression language, tag files, and a simpler tag extension API, among other features. This makes it easier than ever for you to build pages based on JSP technology.
<HTML> <BODY> <% // This is a scriptlet. Notice that the "date" // variable we declare here is available in the // embedded expression later on. System.out.println( "Evaluating date now" ); java.util.Date date = new java.util.Date(); %> Hello! The time is now <%= date %> </BODY> </HTML>
<HTML> <BODY> <% // This scriptlet declares and initializes "date" System.out.println( "Evaluating date now" ); java.util.Date date = new java.util.Date(); %> Hello! The time is now <% // This scriptlet generates HTML output out.println( String.valueOf( date )); %> </BODY> </HTML>
The ISPI (Internet Services Application Programming Interface) filter
AJP - Apache JServ Protocol
To execute a servlet it is necessary to connect the web
server to a servlet engine (e.g. Tomcat or Apache/Tomcat) and to
configure the web server in such a way it can recognize which clients' requests
are directed to a servlet.
javax.servlet.GenericServlet class in J2EE
GenericServlet class derives form java.lang.Object
class and implements Serializable, Servlet and ServletConfig
interfaces. All servlets we'll develop in this document extend GenericServlet
class or others derived from it. Now we are going to describe GenericServlet
class methods.
All methods described above can be overwritten. It is often necessary to overwrite the init() method. When we decide to overwrite init() method it is important to remember:
1. New init() method has to manage the UnavailableException
exception thrown on errors.
2. Parameters in the ServletConfig object have to be saved so that
they'll be available to getServletConfig() method.
To simplify our work, it is possible to insert in new init() method the
line: super.init(ServletConfig).
It could be a good idea to overwrite the destroy() method too when our
servlet executes long operations. In this way we'll be sure long operations will
not be interrupted and that the servlet exits only when all clients have been
served.
java.lang.Object
javax.servlet.GenericServlet
javax.servlet.http.HttpServlet
provides an abstract class to be subclassed to create an HTTP servlet suitable
for a Web site. A subclass of HttpServlet
must override at least
one method, usually one of these:
doGet
, if the servlet supports HTTP GET requests
doPost
, for HTTP POST requests
doPut
, for HTTP PUT requests
doDelete
, for HTTP DELETE requests
init
and destroy
, to manage resources that are
held for the life of the servlet
getServletInfo
, which the servlet uses to provide
information about itself There's almost no reason to override the service
method.
service
handles standard HTTP requests by dispatching them to the handler
methods for each HTTP request type (the do
XXX methods listed
above).
1 import java.io.PrintWriter; 2 import java.io.IOException; 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 8 public class BasicServlet extends HttpServlet { 9 10 public void doGet(HttpServletRequest request, HttpServletResponse response) 11 throws IOException, ServletException { 12 13 response.setContentType("text/html"); 14 15 PrintWriter out = response.getWriter(); 16 out.println("<HTML>"); 17 out.println("<BODY>"); 18 out.println("<HEAD>"); 19 out.println("<TITLE>A Basic Servlet</TITLE>"); 20 out.println("</HEAD>"); 21 out.println("<BODY>"); 22 out.println("<H1>A Basic Servlet</H1>"); 23 out.println("<P>"); 24 out.println("This page was produced by a servlet. Oh boy."); 25 out.println("</BODY>"); 26 out.println("</HTML>"); 27 } 28 }
init()
- called when servlet instantiated
service()
- invoked with new thread for each client request
doXXX()
- called by service()
for GET
, POST
,
HEAD
, OPTIONS
, TRACE
, DELETE
,
PUT
SingleThreadModel
- tag interface implemented by thread-unsafe servlets
destroy()
- called before unloading a servlet
doGet()
and doPost()
doGet()
, doPost()
, or both
doGet()
- called by service()
for GET
requests
doPost()
- called by service()
for POST
requests
getLastModified()
- used to set Last-Modified
headers, respond
properly to If-Modified-Since
requests (304 Not Modified
)1 // ParamServlet.java 2 3 import java.io.PrintWriter; 4 import java.io.IOException; 5 import javax.servlet.ServletException; 6 import javax.servlet.ServletConfig; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class ParamServlet extends HttpServlet { 12 13 String DEFAULT_QUESTION = "(2 * b) || !(2 * b)"; 14 String DEFAULT_ANSWER = "Get thee to a nunnery!"; 15 String question; 16 String answer; 17 18 public void init(ServletConfig config) 19 throws ServletException { 20 21 super.init(config); 22 23 question = config.getInitParameter("question"); 24 if (question == null) { 25 question = DEFAULT_QUESTION; 26 } 27 28 answer = config.getInitParameter("answer"); 29 if (answer == null) { 30 answer = DEFAULT_ANSWER; 31 } 32 } 33 34 public void doGet(HttpServletRequest request, HttpServletResponse response) 35 throws IOException, ServletException { 36 37 response.setContentType("text/html"); 38 39 PrintWriter out = response.getWriter(); 40 out.println("<HTML>"); 41 out.println("<BODY>"); 42 out.println("<HEAD>"); 43 out.println("<TITLE>A Servlet that uses Parameters</TITLE>"); 44 out.println("</HEAD>"); 45 out.println("<BODY>"); 46 out.println("<H1>Q & A</H1>"); 47 out.println("<P>"); 48 out.println("Question: " + question); 49 out.println("<P>"); 50 out.println("Answer: " + answer); 51 out.println("</BODY>"); 52 out.println("</HTML>"); 53 } 54 }
1 // ModificationTimeServlet.java 2 3 import java.io.PrintWriter; 4 import java.io.IOException; 5 import javax.servlet.ServletException; 6 import javax.servlet.ServletConfig; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class ModificationTimeServlet extends HttpServlet { 12 13 String DEFAULT_QUESTION = "(2 * b) || !(2 * b)"; 14 String DEFAULT_ANSWER = "Get thee to a nunnery!"; 15 String question; 16 String answer; 17 private long modificationTime; // in millisecs 18 19 public void init(ServletConfig config) 20 throws ServletException { 21 22 super.init(config); 23 24 question = config.getInitParameter("question"); 25 if (question == null) { 26 question = DEFAULT_QUESTION; 27 } 28 29 answer = config.getInitParameter("answer"); 30 if (answer == null) { 31 answer = DEFAULT_ANSWER; 32 } 33 34 // Round to nearest second 35 modificationTime = (System.currentTimeMillis() / 1000) * 1000; 36 } 37 38 public long getLastModified(HttpServletRequest request) { 39 40 return modificationTime; 41 } 42 43 public void doGet(HttpServletRequest request, HttpServletResponse response) 44 throws IOException, ServletException { 45 46 response.setContentType("text/html"); 47 48 PrintWriter out = response.getWriter(); 49 out.println("<HTML>"); 50 out.println("<BODY>"); 51 out.println("<HEAD>"); 52 out.println("<TITLE>A Servlet that uses Parameters</TITLE>"); 53 out.println("</HEAD>"); 54 out.println("<BODY>"); 55 out.println("<H1>Q & A</H1>"); 56 out.println("<P>"); 57 out.println("Question: " + question); 58 out.println("<P>"); 59 out.println("Answer: " + answer); 60 out.println("</BODY>"); 61 out.println("</HTML>"); 62 } 63 }
GET
or POST
via methods of HttpServletRequest
getParameter(String)
returns:
String
value from form
""
if param exists but no value
null
if param doesn't exist
getParameterValues(String)
returns:
null
if param doesn't exist
getParameterNames()
returns unordered Enumeration
of names
1 // FormServlet.java 2 3 import java.io.PrintWriter; 4 import java.io.IOException; 5 import javax.servlet.ServletException; 6 import javax.servlet.ServletConfig; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class FormServlet extends HttpServlet { 12 13 public void doGet(HttpServletRequest request, HttpServletResponse response) 14 throws IOException, ServletException { 15 16 response.setContentType("text/html"); 17 18 PrintWriter out = response.getWriter(); 19 out.println("<HTML>"); 20 out.println("<BODY>"); 21 out.println("<HEAD>"); 22 out.println("<TITLE>A Form Servlet</TITLE>"); 23 out.println("</HEAD>"); 24 out.println("<BODY>"); 25 out.println("<H1>A Servlet in Top Form</H1>"); 26 out.println("<P>"); 27 out.println("Name: " + request.getParameter("name")); 28 out.println("<P>"); 29 out.println("Rank: " + request.getParameter("rank")); 30 out.println("<P>"); 31 out.println("Serial Number: " + request.getParameter("serial")); 32 out.println("</BODY>"); 33 out.println("</HTML>"); 34 } 35 36 public void doPost(HttpServletRequest request, HttpServletResponse response) 37 throws IOException, ServletException { 38 39 doGet(request, response); 40 } 41 }
1 <HTML> 2 <HEAD> 3 <TITLE>A Form for a Servlet</TITLE> 4 </HEAD> 5 <BODY> 6 <CENTER> 7 <H1>We Have Ways To Make You Talk</H1> 8 <FORM action="/examples/servlet/FormServlet"> 9 <TABLE> 10 <TR> 11 <TD> 12 <STRONG>Name:</STRONG> 13 </TD> 14 <TD> 15 <INPUT type="text" name="name"> 16 </TD> 17 </TR> 18 <TR> 19 <TD> 20 <STRONG>Rank:</STRONG> 21 </TD> 22 <TD> 23 <INPUT type="text" name="rank"> 24 </TD> 25 </TR> 26 <TR> 27 <TD> 28 <STRONG>Serial Number:</STRONG> 29 </TD> 30 <TD> 31 <INPUT type="text" name="serial"> 32 </TD> 33 </TR> 34 <TR> 35 <TD colspan="2" align="center"> 36 <INPUT type="submit" value="Submit"> 37 </TD> 38 </TR> 39 </TABLE> 40 </FORM> 41 </CENTER> 42 </BODY> 43 </HTML>
1 // In file Servlets/ex5/AllParamsServlet.java 2 3 import java.io.PrintWriter; 4 import java.io.IOException; 5 import java.util.Enumeration; 6 import javax.servlet.ServletException; 7 import javax.servlet.ServletConfig; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 public class AllParamsServlet extends HttpServlet { 13 14 public void doGet(HttpServletRequest request, HttpServletResponse response) 15 throws IOException, ServletException { 16 17 response.setContentType("text/html"); 18 19 PrintWriter out = response.getWriter(); 20 out.println("<HTML>"); 21 out.println("<BODY>"); 22 out.println("<HEAD>"); 23 out.println("<TITLE>A Servlet that Reports all Parameters</TITLE>"); 24 out.println("</HEAD>"); 25 out.println("<BODY>"); 26 out.println("<H1>The Parameters and Their Values:</H1>"); 27 28 Enumeration names = request.getParameterNames(); 29 while (names.hasMoreElements()) { 30 out.println("<P>"); 31 String name = (String) names.nextElement(); 32 String value = request.getParameter(name); 33 out.println("Parameter Name: " + name + "<BR>"); 34 out.println("Parameter Value: " + value); 35 } 36 37 out.println("</BODY>"); 38 out.println("</HTML>"); 39 } 40 41 public void doPost(HttpServletRequest request, HttpServletResponse response) 42 throws IOException, ServletException { 43 44 doGet(request, response); 45 } 46 }
getHeader(String headerName)
returns String
value or null
getHeaders(String headerName)
returns Enumeration
of values of
all occurances
getHeaderNames()
returns Enumeration
of all header names in
request
getCookies()
: Cookie
header as Cookie[]
getContentLength()
: Content-Length
header (num bytes
sent by POST
)
getAuthType()
and getRemoteUser()
: parsed
Authorization
header
getContentType()
: Content-Type
header (for data attached via
POST
or PUT
getMethod()
: GET
, POST
, HEAD
, etc.
getRequestURI()
: URL between port and ?
getProtocol()
: HTTP/1.0
, HTTP/1.1
, etc.
Accept
: MIME types client can accept
Accept-Charset
: Character set client can handle: ISO-8859-1
, etc.
Connection
: whether to keep socket open: keep-alive
or
close
From
: email address of requestor (used by spiders)
Host
: host and port in original URL
If-Modified-Since
: send only if newer
Pragma
: value no-cache
tells proxies to always forward request
Referer
: URL of referring web page
User-Agent
: browser or client
1 // CompressServlet.java 2 3 import java.io.PrintWriter; 4 import java.io.IOException; 5 import java.io.OutputStream; 6 import javax.servlet.ServletException; 7 import javax.servlet.ServletConfig; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 import java.util.zip.GZIPOutputStream; 12 13 public class CompressServlet extends HttpServlet { 14 15 public void doGet(HttpServletRequest request, HttpServletResponse response) 16 throws IOException, ServletException { 17 18 response.setContentType("text/html"); 19 20 PrintWriter out; 21 String zipped = " (Compressed Document)"; 22 23 String acceptedEncodings = request.getHeader("Accept-Encoding"); 24 if ((acceptedEncodings != null) 25 && (acceptedEncodings.indexOf("gzip") != -1)) { 26 27 // GZIP is accepted, so send a compressed document 28 OutputStream gzipper = new GZIPOutputStream(response.getOutputStream()); 29 out = new PrintWriter(gzipper); 31 response.setHeader("Content-Encoding", "gzip"); 32 } 33 else { 34 out = response.getWriter(); 35 zipped = " (Uncompressed Document)"; 36 } 37 38 out.println("<HTML>"); 39 out.println("<BODY>"); 40 out.println("<HEAD>"); 41 out.println("<TITLE>A Romantic Servlet" + zipped + "</TITLE>"); 42 out.println("</HEAD>"); 43 out.println("<BODY>"); 44 out.println("<H1>How do I love thee? Let me count the ways.</H1>"); 45 46 out.println("<P>"); 47 48 for (int i = 1; i < Integer.MAX_VALUE; ++i) { 49 out.print(Integer.toString(i) + ", "); 50 if ((i % 100) == 0) { 51 out.println(""); 52 out.println("<P>"); 53 } 54 } 55 56 out.println(Integer.toString(Integer.MAX_VALUE)); 57 58 out.println("</BODY>"); 59 out.println("</HTML>"); 60 } 61 62 public void doPost(HttpServletRequest request, HttpServletResponse response) 63 throws IOException, ServletException { 64 65 doGet(request, response); 66 } 67 }
|
HTTP/1.1 200 OK Content-Type: text/plain Think Objects! |
PrintWriter
isn't buffered
get/setBufferSize()
and isCommited()
setStatus(int)
: standard waySC_NOT_FOUND
, etc.)
sendError(int code, String msg)
: sends status code plus HTML formatted msg
sendRedirect(String url)
: generates 302 response and Location
header with value url
setHeader(String hdr, String val)
: sets header to value
setDateHeader(String hdr, long ms)
: sets header to millisecs since epoch
converted to date
setIntHeader(String hdr, int val)
: sets header to val
converted to
string
setContentType()
: sets Content-Type
setContentLength()
: sets Content-Length
(for persistent connections)
addCookie()
: inserts a cookie into Set-Cookie
sendRedirect(String url)
: sets Location
to url
plus status code to 302
getRequestProtocol()
before using 1.1-only headers
Content-Encoding
: compression technique
Content-Language
: language of the data
string
Content-Length
: bytes of data being sent
Content-Type
: MIME type
Last-Modified
: when data was last changed
Pragma
: no-cache
for 1.0 clients
Set-Cookie
: set a cookie
Cache-Control
Headerpublic
: cacheable
private
: for single user, cache only in private store
no-cache
: never cache (same as Pragma: no-cache
)
no-store
: don't cache or even make a temp file
must-revalidate
: always go back to source
proxy-revalidate
: shared caches must always go back to source
max-age=xxx
: consider stale after xxx
seconds
s-max-age=xxx
: shared caches should consider data stale after
xxx
seconds
Refresh
HeadersetIntHeader("Refresh", 60);or
setHeader("Refresh", "5; http://www.sorcer.cs.ttu.edu/realindex.html");
Note that this is commonly set via <META HTTP-EQUIV="Refresh"
CONTENT="5; URL=http://host/path">
in the HEAD
section of
the HTML page, rather than as an explicit header from the server.
But for servlets, setting the header directly is easier and clearer. Note
that this header means "reload this page or go to the specified URL in N
seconds." It does not mean "reload this page or go to the specified URL
every N seconds." So you have to send a Refresh
header each time, and sending a 204 (No Content) status code stops the browser
from reloading further, regardless of whether you explicitly send the
Refresh
header or use <META HTTP-EQUIV="Refresh" ...>
.
HttpSession
uses cookies, if supported,
else URL-rewriting (encodeURL(String)
)HttpSession
HttpSession session = request.getSession(true);
getAttribute(String name)
- get a previously
stored Object
value
setAttribute(String name, Object value)
-
associate a value with a name
HttpSessionBindingListener
,
valueBound()
or valueUnbound()
called
removeAttribute(String name)
- removes any
value associated with name
getAttributeNames()
- get names of all attributes
for a session
getID()
- returns unique String
identifier
assigned to this session
isNew()
- true
if just created
getCreationTime()
- returns the time when this session was
created
getLastAccessTime()
- returns time when client last
sent a request associated with the session
get/setMaxInactiveInterval()
- get or set the number
of seconds after which a session should be automatically inactivatedinvalidate()
- invalidates this session then unbinds any
objects bound to it.URL rewriting involves placing the session key (normally stored as jsessionid in a browser cookie) as a parameter in every HTML link in a web page. This is necessary when a browser has cookie support disabled. Every URL written out by a servlet or JSP page should be run through the following methods in the servlet API:
public String HttpServletResponse.encodeURL( String url ); public String HttpServletResponse.encodeRedirectURL( String url );
The latter method is used to encode any URL used as an argument in the sendRedirect method. If the user's browser does support cookies, the URLs are simply returned unchanged. Session tracking via URLs can lead to a single browser supporting multiple sessions through several windows.
Example: insteadout.print("<HR><A HREF=\"");use:
out.print(req.getRequestURI());
out.print("\">Back to the shop</A></BODY></HTML>");
out.print("<HR><A HREF=\""); out.print(res.encodeUrl(req.getRequestURI())); out.print("\">Back to the shop</A></BODY></HTML>");
creates:
http://yucca.cs.ttu.edu/servlets-examples/servlet/ShoppingCartServlet2;jsessionid=E9177C551F54C53D847764C63233AD43
ShoppingCartServlet,
ShoppingCartServlet2
This section shows how to
Session Tracking allows a Servlet to associate a request with a user. A session can extend across requests and connections of the stateless HTTP. Sessions can be maintained in two ways:
Our next Servlet manages a virtual shopping cart. Users can add various items to their shopping cart via HTML forms. The shopping cart contents are stored on the server and each user gets his own shopping cart which is selected automatically whenever he makes a request to the Servlet.
In the simplified version that we implement in class
ShoppingCartServlet
there are only two kinds of items, named FOO
and BAR. By pressing a button in an HTML form a single FOO or
BAR item can be put into the shopping cart. There's another button to
see the current contents of the shopping cart and a button to order the
selected items, thus clearing the shopping cart.
The first version of the Servlet, called
ShoppingCartServlet
,
which works with Cookie-style sessions only, consists of the two standard
methods, doGet
and doPost
:
doGet
method.doPost
method processes the form data which is sent
by a client in response to the form created by doGet
.First we get the HttpSession
object which is associated
with the request by calling req.getSession
. The argument
true
forces the creation of a new session if the request
doesn't contain a valid session key.
Note: Although getSession
is a method
of HttpServletRequest
and not of HttpServletResponse
it may modify the response header and therefore needs to be called
before a ServletOutputStream
or PrintWriter
is
requested.
If the session is indeed new (determined by calling HttpSession
's
isNew()
method) we add some custom data to the session: Two
counters, one for the FOOs and one for the BARs in the
shopping cart. The session object can be used like a Dictionary
.
That means we can only add Objects, not instances of primitive
types like int. We could use an instance of
java.lang.Integer
for each counter, but these objects are
immutable which makes incrementing inefficient and difficult to
implement. Instead we use an array of int (int[]
)
with only one element as a mutable wrapper object. The element is
initialized to 0.
Next we retrieve the values for "foo" and "bar" from the session, no matter if they were just added or carried over from a previous request.
In the ListManagerServlet
both buttons had the same name
but different values so we could use getParameter
to
retrieve the value from the request and then do a string compare to the
possible values. This time we use a different approach which can be
implemented more efficiently. All buttons have different names and we
can find out which button was used to submit the form by checking which
name has a non-null value.
A new FOO or BAR item can be put into the shopping cart by simply incrementing the counter in the array. Note that the array does not need to be put back into the session because it has not changed itself, only the contents have been modified.
When the user chooses to buy the contents of the shopping cart we
call session.invalidate()
to delete the session on the
server side and tell the client to remove the session ID Cookie. The
session data is lost and when a new POST request is made to the
Servlet, a new session will be created.
Note that req.getSession
is called for every POST
request. It is important that the session object is requested on a regular
basis because the Web Server may set a session timeout. Requesting the
session ensures that the session's time-to-live is reset. The only reason
for not calling req.getSession
in the doGet
method
of this version of the Servlet is to make the response to doGet
cachable.
To make the Servlet usable with URL rewriting (for clients without Cookie support or with Cookie support turned off) we have to make some modifications.
The formerly static "Online Shop" page which is created by doGet
needs to be modified to include an ACTION URL which contains an
encoded session ID in the HTML form. This is done with the encodeUrl
method of HttpServletResponse
. We also need to call
req.getSession
to keep the session alive. The additional code to
check for a new session can be avoided by using getSession(false)
.
If there is no session or an invalid session we do not force the creation of
a new session. This is deferred until the doPost
method is
called. Finally, the response has to be marked as not cachable by calling
res.setHeader("pragma", "no-cache")
, as usual.
The doPost
method requires only a minor change. The
Servlet's URI which is used to link back to the "Online Shop" page needs to
be encoded with res.encodeUrl
, as in the doGet
method.
Beginning with version 2.1 of the Servlet API, the abbrevation
URL is consistently spelled in upper case in all method names.
The old method names have been deprecated but are still supported in
2.1. The method encodeUrl which is used in the shopping
cart Servlet should be replaced by encodeURL when
writing a 2.1-compliant Servlet. |
Modified Cart Servlet is available as
ShoppingCartServlet2
.
HTTP is “stateless”
Protocols that maintain “state” are complex!
try { // With components. URL url = new URL("http", "hostname", 80, "index.html"); // With a single string. url = new URL("http://hostname:80/index.html"); } catch (MalformedURLException e) { }
URI uri = null; URL url = null; // Create a URI try { uri = new URI("file://D:/almanac1.4/Ex1.java"); } catch (URISyntaxException e) { } // Convert an absolute URI to a URL try { url = uri.toURL(); } catch (IllegalArgumentException e) { // URI was not absolute } catch (MalformedURLException e) { } // Convert a URL to a URI try { uri = new URI(url.toString()); } catch (URISyntaxException e) { }
try { URL url = new URL("http://hostname:80/index.html#_top_"); String protocol = url.getProtocol(); // http String host = url.getHost(); // hostname int port = url.getPort(); // 80 String file = url.getFile(); // index.html String ref = url.getRef(); // _top_ } catch (MalformedURLException e) {
}
try { // Construct data String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8"); data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8"); // Send data URL url = new URL("http://hostname:80/cgi"); URLConnection conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write(data); wr.flush(); // Get the response BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = rd.readLine()) != null) { // Process line... } wr.close(); rd.close(); } catch (Exception e) { }
try { // Create a URL for the desired page URL url = new URL("http://hostname:80/index.html"); // Read all the text returned by the server BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); String str; while ((str = in.readLine()) != null) { // str is one line of text; readLine() strips the newline character(s) } in.close(); } catch (MalformedURLException e) { } catch (IOException e) { }
try { // Create a URL for the image's location URL url = new URL("http://hostname:80/image.gif"); // Get the image java.awt.Image image = java.awt.Toolkit.getDefaultToolkit().getDefaultToolkit().createImage(url); } catch (MalformedURLException e) { } catch (IOException e) { }
try { // Create a URL that refers to a jar file on the net URL url = new URL("jar:http://hostname/my.jar!/"); // Create a URL that refers to a jar file in the file system url = new URL("jar:file:/c:/almanac/my.jar!/"); // Get the jar file JarURLConnection conn = (JarURLConnection)url.openConnection(); JarFile jarfile = conn.getJarFile(); // When no entry is specified on the URL, the entry name is null String entryName = conn.getEntryName(); // null // Create a URL that refers to an entry in the jar file url = new URL("jar:file:/c:/almanac/my.jar!/com/mycompany/MyClass.class"); // Get the jar file conn = (JarURLConnection)url.openConnection(); jarfile = conn.getJarFile(); // Get the entry name; it should be the same as specified on URL entryName = conn.getEntryName(); // Get the jar entry JarEntry jarEntry = conn.getJarEntry(); } catch (MalformedURLException e) { } catch (IOException e) { }
// Install the custom authenticator Authenticator.setDefault(new MyAuthenticator()); // Access the page try { // Create a URL for the desired page URL url = new URL("http://hostname:80/index.html"); // Read all the text returned by the server BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); String str; while ((str = in.readLine()) != null) { // str is one line of text; readLine() strips the newline character(s) } in.close(); } catch (MalformedURLException e) { } catch (IOException e) { } public class MyAuthenticator extends Authenticator { // This method is called when a password-protected URL is accessed protected PasswordAuthentication getPasswordAuthentication() { // Get information about the request String promptString = getRequestingPrompt(); String hostname = getRequestingHost(); InetAddress ipaddr = getRequestingSite(); int port = getRequestingPort(); // Get the username from the user... String username = "myusername"; // Get the password from the user... String password = "mypassword"; // Return the information return new PasswordAuthentication(username, password.toCharArray()); } }
try { // Create a URLConnection object for a URL URL url = new URL("http://hostname:80"); URLConnection conn = url.openConnection(); // List all the response headers from the server. // Note: The first call to getHeaderFieldKey() will implicit send // the HTTP request to the server. for (int i=0; ; i++) { String headerName = conn.getHeaderFieldKey(i); String headerValue = conn.getHeaderField(i); if (headerName == null && headerValue == null) { // No more headers break; } if (headerName == null) { // The header value contains the server's HTTP version } } } catch (Exception e) { }
Here's a sample of headers from a website:
Key=Value null=HTTP/1.1 200 OK Server=Netscape-Enterprise/4.1 Date=Mon, 11 Feb 2002 09:23:26 GMT Cache-control=public Content-type=text/html Etag="9fa67d2a-58-71-3bbdad3283" Last-modified=Fri, 05 Oct 2001 12:53:06 GMT Content-length=115 Accept-ranges=bytes Connection=close
When the server wants to set a cookie in the client, it includes a response header of the form
Set-Cookie: cookie-value; expires=date; path=path; domain=domain-name; secure
cookie-value
is some arbitrary string data that should be returned to the server in future
URL requests. The life time of the cookie is specified by
expires
.
If expires
is not specified, the cookie expires at the end of the session. When a URL
request is made, the cookie should be sent along only if
domain-name
matches the end of the fully-qualified host name of the URL request and
path
matches the beginning of the path of the URL request. If
secure
is
specified, the cookie should be sent to the server only through HTTPS.
try { // Create a URLConnection object for a URL URL url = new URL("http://hostname:80"); URLConnection conn = url.openConnection(); // Get all cookies from the server. // Note: The first call to getHeaderFieldKey() will implicit send // the HTTP request to the server. for (int i=0; ; i++) { String headerName = conn.getHeaderFieldKey(i); String headerValue = conn.getHeaderField(i); if (headerName == null && headerValue == null) { // No more headers break; } if ("Set-Cookie".equalsIgnoreCase(headerName)) { // Parse cookie String[] fields = headerValue.split(";\\s*"); String cookieValue = fields[0]; String expires = null; String path = null; String domain = null; boolean secure = false; // Parse each field for (int j=1; j<fields.length; j++) { if ("secure".equalsIgnoreCase(fields[j])) { secure = true; } else if (fields[j].indexOf('=') > 0) { String[] f = fields[j].split("="); if ("expires".equalsIgnoreCase(f[0])) { expires = f[1]; } else if ("domain".equalsIgnoreCase(f[0])) { domain = f[1]; } else if ("path".equalsIgnoreCase(f[0])) { path = f[1]; } } } // Save the cookie... } } } catch (MalformedURLException e) { } catch (IOException e) { }
Here's a sample of cookies from two websites:
B=a43ka6gu6f4n4&b=2; expires=Thu, 15 Apr 2010 20:00:00 GMT; path=/; domain=.yahoo.com PREF=ID=e51:TM=686:LM=86:S=BL-w0; domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT
javax.servlet.http.Cookie - defined in servlet API
Java 2 Platform
Enterprise Edition, v 1.4 API Specification
HttpServletResponse.addCookie(javax.servlet.http.Cookie)
method. HttpServletRequest.getCookies()
method. try { // Create a URLConnection object for a URL URL url = new URL("http://hostname:80"); URLConnection conn = url.openConnection(); // Set the cookie value to send conn.setRequestProperty("Cookie", "name1=value1; name2=value2"); // Send the request to the server conn.connect(); } catch (MalformedURLException e) { } catch (IOException e) { }