Advanced Java Programming Unit Two: Servers and Servlets

advertisement
Gareth
Lee
John
Morris
Advanced Java Programming
Unit Two: Servers and Servlets
Gareth Lee
Department of Electrical and Electronic Engineering,
University of Western Australia
Overview
• To create a simple HTTP server in Java
• To use the implementation to illustrate a
number of advanced Java features:
•
•
•
•
TCP/IP Sockets and Server Sockets
Interfaces
Software components (more from John later)
Multithreading
• To show how to create executable server
objects (using Sun’s Servlets API)
Recommended Reading
• Java Network Programming, Elliotte Rusty
Harold, O’Reilly and Associates, 1997,
ISBN 1-56592-227-1
• TCP/IP Network Administration, Second
Edition, Craig Hunt, O’Reilly and
Associates, 1997, ISBN 1-56592-322-7
• The Java Developer’s connection:
http://www.javasoft.com/jdc
• The Javadoc documentation
(Pseudo) requirements
• Server must be able to process HTTP/1.0
file transfer requests and deliver files
• Connections are to be made via TCP/IP
• Must be efficient and prompt
• Must be simple to understand and elegant
in design
HTTP protocol
• Developed by Tim Berners-Lee at CERN
• Like most Internet protocols it is described
in an RFC (Request for Comment
document): RFC1945
• May be downloaded from the Internet
Engineering Task Force’s web site:
http://www.ietf.org
Back to server example
• Some of you may have covered this in the
introductory Java course
• Servers have a listener loop
• Loop until the server is shutdown
• Wait for a client to request a connection
• Read the details of the client’s request
• Provide the requested information to the
client
• Here’s the listener loop from our example:
HttpServer
ServerSocket socket = new ServerSocket(80, 5);
public void listen()
throws IllegalAccessException,
InstantiationException,
IOException
{
for (;;) {
System.err.println("HttpServer: waiting...");
Socket s = socket.accept();
FileServer f = createFileServer();
f.dispatch(s);
}
}
How it all fits together
Client (sid)
s = new Socket
(“fred”, 80)
Server (fred)
2037
80
2037
1583
s.getInputStream() 2037
s.getOuputStream()
ServerSocket ss.
s = ss.accept()
Socket s
1583 s.getInputStream()
s.getOuputStream()
…but more of that later!
• Good software is designed in a modular
fashion avoiding stovepipe designs!
• This is a form of software components
• Java has strong support for components
• Components hide their implementation
behind interfaces
• An interface defines a contract between
the supplier/server and the user/client.
How clients use interfaces
ServerSocket socket = new ServerSocket(80, 5);
public void listen()
throws IllegalAccessException,
InstantiationException,
IOException
{
for (;;) {
System.err.println("HttpServer: waiting...");
Socket s = socket.accept();
FileServer f = createFileServer();
f.dispatch(s);
}
}
Interfaces benefit clients
• Simplifies client implementation
• Clients do not need to worry about the
implementation details
• Interfaces encapsulate state of different
subsystems  side effects reduced
• Define clear boundaries between different
teams of programmers
• Clients can substitute alternative
implementations: polymorphism
• Clients can purchase off the shelf
solutions: software components
Interfaces simplify clients
Client Program
Interface
Software Component
/ublic class HttpServer
{
/**
Listens indefinitely for transfer requests and creates a server
instance for each request.
*/
public void listen()
throws IllegalAccessException, InstantiationException, IOException
{
for (;;) {
/*
Block, waiting for a request to occur then spawns a new
(anonymous) socket with which to deal with the request.
*/
System.err.println("HttpServer: waiting...");
Socket s = socket.accept();
/*
Create a file server to deal with the new socket.
*/
FileServer f = createFileServer();
f.dispatch(s);
}
}
public static void main(String[] args)
{
try {
HttpServer htts = new HttpServer("sea.server.ThreadedFileServer");
htts.listen();
}
catch (Exception e) {
System.err.println("HttpServer: failed due to exception:\n" + e);
}
}
The FileServer interface
public interface FileServer
{
/**
This method allows an incoming HTTP request to initiate a
file dispatch. The socket will provide an input stream (which
is at the beginning) from which an HTTP/1.0 header request may
be read.<p>
It also provides an output stream on which the request should be
delivered. The delivery should have an HTTP/1.0 header
prepended.
@param s The socket on which a request is being made.
Once this method has returned the socket will have
been closed by the dispatcher.
*/
public void dispatch(Socket s);
}
Interfaces are contracts
• Each interface is a contract between two
parties
• The contract should be made as strict and
precise as possible
• Avoid unnecessary ambiguity
• Document the contract within the
interface’s source file using Javadoc
Implementing FileServer
• Two flavours of FileServer have been
provided using deferred instantiation
• A simple one but with low performance:
sea.server.SimpleFileServer
• A server that uses multiple threads to increase
performance: sea.server.ThreadedFileServer
• A server which uses a pool of threads to
achieve the maximum possible performance:
sea.server.ThreadedServer2
SimpleFileServer (1)
• Must implement the FileServer interface so
that it can plug in to the HttpServer
• Reads the HTTP request from the Socket’s
input stream
• Decides which file is required
• Reads the file and spools to the Socket’s
output stream.
SimpleFileServer (2)
public class SimpleFileServer implements FileServer
{
protected Socket s = null;
public void dispatch(Socket s)
{
this.s = s;
respond();
}
. . . .
}
SimpleFileServer (3)
• Must get an input stream so that we can
analyse the request
• Socket provides the method
• InputStream getInputStream();
Socket s;
InputStream inStream = s.getInputStream();
InputStreamReader reader = new InputStreamReader(inStream);
BufferedReader input = new BufferedReader(reader);
SimpleFileServer (4)
• Request consists of a number of lines of
text separated by “\r\n”
• First line is all this server is interested in
• A typical request might be of the form:
GET /path/to/file.html HTTP/1.0
Accept: text/html
Accept: image/gif
User-Agent: Lynx/2.4
SimpleFileServer (5)
• Cuts out the file name
• Looks for the file relative to the current
working directory (not portable!!)
• If the file is a directory look for the file
“index.html” in the directory
• If the file does not exist then respond with
an error (code 404)
SimpleFileServer (6)
• Must construct a header for the response
• Code 200 means success
• Simple header takes the following form:
HTTP/1.0 200 OK
Server: SEA/1.0
MIME-version: 1.0
Content-type: text/html
Data starts after blank line. . .
More data, etc. . .
SimpleFileServer (7)
• Get the output stream from the Socket
• OutputStream getOutputStream()
• Spool (copy) the file contents into the
socket
• If the MIME type is textual then we must
make sure the lines are delimited by “\r\n”.
• Otherwise we pass the file unmodified
Server performance (1)
• The SimpleFileServer is completely
sequential.
• It handles one request at a time.
• Reading a file from disk takes a long time
(around 10ms)
• The server will be sitting idle while it waits
for the file to load (wasting up to 106
instruction cycles)
• Other web browsers will be kept waiting
Server performance (2)
time
Start HTTP request loading
Block awaiting disk availability
Deliver web page across network
Threaded servers (1)
• Threaded servers can process several
requests at once. Each request is handled
by a separate thread.
• This doesn’t increase the overall amount
of work done (unless using SMP)
• . . . but it does reduce the wastage!
• Threaded operation is worthwhile when
threads are expected to block, awaiting I/O
operations
Threaded servers (2)
time
Start HTTP request loading
Block awaiting disk availability
Deliver web page across network
Threaded FileServer (1)
• Java provides very convenient
multithreading to programmers
• We can add threads using inheritance
• We can supplement the existing capabilities of
the SimpleFileServer class
• We create a class ThreadedFileServer which
extends the existing SimpleFileServer
• You may have covered threads in the
Introductory Java Course
Threaded FileServer (2)
public class ThreadedFileServer extends SimpleFileServer
implements FileServer, Runnable
{
private static int index = 0;
public void dispatch(Socket s) {
super.s = s;
Thread thread =
new Thread(this, ”Server-" + (index++));
thread.start();
}
public void run() {
super.respond();
}
}
java.lang.Thread (1)
• Creates new threads within the virtual
machine
• Classes which start threads must
implement interface java.lang.Runnable
interface Runnable
{
/**
This is the method that will be run when the
new thread is started.
*/
public void run();
}
java.lang.Thread (2)
• Must create a Thread object associated
with each new thread using the
constructor
• Thread(Runnable run, String threadName)
• Start a thread with the method
• void start()
• Other useful methods can be used to set
priorities and interrupt a running thread
java.lang.Thread (3)
• Our threads do not share any common
memory locations (except for index)
• When threads read/write a shared memory
area access must be synchronized
• Otherwise it is impossible to predict how
the system will behave
• Java has mechanisms for achieving this
But even threads cost
• Starting a thread can be relatively
expensive when performance is critical
• Our threaded server creates a new Thread
for each file to be transferred
• A better approach is to create a pool of
threads and recycle them
• Create a pool of threads which are ready to
work when needed
• Have threads wait until work is available
• Better, but more complex so look at the
class sea.server.ThreadedFileServer2
Making the server programmable
• Our example web server performs a very
simple task
• Accept a request from a client
• Retrieve the appropriate document from disk
• Return the document to the client
• This is too limiting
• How do we implement searches?
• We need to be able to run programs within
the server to process user requests
• Accept a client request including arguments
• Run a program on the arguments
• Return results in the form of a document
Servlets
• When we run small Java programs within a
browser these are referred to as Applets. . .
• so we run small Java programs within a
server these are “Servlets”
• A servlet is a program designed to process
a client request (which requires
interactivity).
• It processes arguments and formats its results
as a short lived document.
• HTML servlets are becoming a popular
mechanism for creating interactive
servers.
Servlets versus CGI (1)
• Traditionally programs were run on web
servers using Common Gateway Interface
(CGI) scripts written in languages such as
Perl.
• Must create a new interpreter process for each
client request
• Comparatively slow to start
• Expensive of memory resources when serving
several clients at the same time
• Interpreted programs are CPU intensive
Servlets versus CGI (2)
• Servlets use Java objects which persist
between requests to the server
• Low latency since requests run in threads
• Offer performance advantages since programs
are compiled and can take advantage of JITs
and/or Hotspot JVMs.
• Servlet groups can share a JVM leading to
smaller memory footprints.
• Servlets run in a Sandbox offering protection
from malicious (or accidental) damage
• Programs are future proofed since WORA
offers better scope for server upgrades.
Creating a simple servlet
• Servlets are written in a similar fashion to
applets
• Write a new servlet class which extends
javax.servlet.http.HttpServlet (or just
implements javax.servlet.Servlet)
• Override certain methods to deal with requests
• Get your methods to create an HTML document
to return information to the client’s browser
• Load the servlet byte codes onto your web
server (for example apache/jserv)
Import servlet methods (1)
• When the servlet is first loaded it makes a
single call to the method
• public void init(ServletConfig config)
• This may optionally be overridden to
initialise the state of the servlet (for example
loading state information from a file).
• When a servlet is finally unloaded it makes
a single call to the method
• public void destroy()
• If you wish to save to servlet state to a file
(or using JDBC) this is the method to
override
Import servlet methods (2)
• To handle an HTTP GET request implement
• protected void doGet(HttpServletRequest request,
HttpServletResponse response)
• If a browser visits your servlet this is where
you get to create a document for it to display
• To handle an HTTP POST request provide
• protected void doPost(HttpServletRequest request,
HttpServletResponse response)
• If your document contains an HTML form
and the user posts the results this is where
you can extract and process them
• Also methods for HTTP OPTIONS, TRACE
and DELETE (more exotic options)
Import servlet methods (3)
• Two objects are passed as parameters to
all these handler methods:
• javax.servlet.http.HttpServletRequest
• Represents the formation that was passed to
the server when the user submitted the request
by visiting/posting to the servlets URL.
• javax.servlet.http.HttpServletResponse
• Used to construct a reponse document that is
returned to the user
• Each has a raft of methods so check the
Javadoc for details
A simple chat server
• An web based chat room server
• A number of users can connect to the
servlet using browsers
• Read a list of the previous messages
• Optionally append new messages to the
list
• Messages are attributed to a specific
author and are time stamped
• Messages do not persist after the chat
server is stopped (easy enough to rectify)
ChatServer (1)
public class ChatServlet extends HttpServlet
{
Vector messages = new Vector();
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
}
public void destroy()
{
// Currently does nothing
}
. . . .
}
ChatServer (2)
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
createDocument(response);
}
protected void createDocument(HttpServletResponse response)
throws IOException {
response.setContentType("text/html");
response.setHeader("pragma", "no-cache");
PrintWriter writer = response.getWriter();
writer.println("<HTML>");
writer.println("<HEAD><TITLE>Chat Servlet</TITLE></HEAD>");
writer.println("<BODY>");
Date now = new Date();
writer.println("Current server time is " + now + "<P>");
. . . .
writer.println("</BODY></HTML>");
writer.close();
}
ChatServer (3)
for (int i = 0; i < messages.size(); i++) {
writer.println("<HR>");
String messageString = (String) messages.elementAt(i);
writer.println(messageString);
}
writer.println("<HR><FORM METHOD=POST>");
writer.println("Enter your name: “ +
“<INPUT TYPE=TEXT SIZE=25 NAME=name><BR>");
writer.println("Enter your message:<BR>” +
“<TEXTAREA ROWS=5 COLS=40 NAME=message>” +
“Type your message here</TEXTAREA><BR>");
writer.println(
"<INPUT TYPE=SUBMIT NAME=action VALUE=Submit>");
writer.println("<HR></FORM>");
ChatServer (4)
protected synchronized void doPost(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
String name = request.getParameter("name");
String message = request.getParameter("message");
if (name != null && message != null) {
Date timeStamp = new Date();
String messageString = "<B>Message " + messages.size() +
" from " + name + " at " + timeStamp +
":</B><BR>" + message + "<P>";
messages.add(messageString);
}
createDocument(response);
}
Performance (1)
• Servlets offer better performance than
most of the previous CGI like technologies
• But CGI/Servlets concentrate the load on
the server
• When designing high throughput servers
only use servlets where you really need
interactivity
• Searches/Shopping carts
• Data that is very short lived (stock quotes)
• This also applies to low throughput
servers that might need to scale later
Performance (2)
• Consider using periodic programs to
generate static documents on disk
• The cost of serving fixed documents will
always be less than the cost of server side
execution
• Disk space is cheap!
• Consider using applets when possible
• This places the load on the client machines
rather than the server
• Finally consider using SMP and/or server
farms
• Complex and very expensive
Pull versus Push transports
• How can a chat reader find out when a new
message has been posted by another
author?
• Only by repeatedly hitting the Reload button!
• HTTP (& TCP/IP services in general)
transfer documents on the user’s request
• To push updates automatically from the
server you will need to:
• Start a reverse server within each client
• Use a multicast group
• Use a remote procedure call system such as
RMI or CORBA
Servlets and JSP
• Java Server Pages is an extension to the
servlets API.
• With conventional servlets you embed the
HTML that you need inside a Java
program.
• With JSP you embed your Java program
within a HTML document (by using special
tags).
• Works rather like JavaScript but the JSP
script runs on the server before the page is
dispatched to the user’s browser.
Useful sources of information
• For information about HTML try
http://www.w3schools.com
• You can download Sun’s servlet
development kit from their web site at the
http://java.sun.com/products/servlet
• You can download apache’s Tomcat server
from http://jakarta.apache.org
• For other information about Servlet
development try http://www.servlets.com
Homework
• Read through the sample code to convince
yourself you understand what’s going on
• Sample code can be downloaded from
http://ciips.ee.uwa.edu.au/~gareth
• Read the code documentation
• If you can, run the examples to check they
work
Comments, Suggestions. . .
• How was the presentation paced?
• Was there enough (or too much) technical
content?
• Any areas of particular interest?
• Comments regarding presentation style?
Download