Programming Servlets

   

Java™ 2 Primer Plus
By Steven Haines, Steve Potts

Table of Contents
Chapter 21.  Servlets


Servlet programming is built on a solid foundation of prewritten Java classes. Instead of creating servlets as Java classes that are started by calling a main method, servlets are extensions of other classes that already know how to interact with Web servers and servlet containers.

The following classes and interfaces are the most important ones to understand when programming servlets:

  • Servlet This interface defines the init(), service(), and destroy() methods. It also defines two more methods that implementing classes must provide, getServletConfig() and getServletInfo(), which allow you to query the servlet for information about the servlet itself (author, version, copyright, and so on). The servlet container is programmed to expect a servlet to implement these five methods. This is how code that you write can be plugged into a framework such as the servlet container so easily. Advanced programmers might want to implement this interface directly in a new class instead of using either the GenericServlet class or HttpServlet class. This would require you to write quite a bit of code, however, and it is not needed to satisfy ordinary requirements.

  • GenericServlet The GenericServlet class provides a simple implementation of the Servlet interface. It is called "Generic" because it does not assume that the protocol it will process will be HTTP. If you were writing your own protocol, you would extend this class. Normally, you override the service() method.

  • HttpServlet This is the class that is most often extended when servlets are written. It extends GenericServlet to provide HTTP-specific processing. Because HTTP is so common, servlets that extend this class tend to be the easiest to write. Normally, you override the doGet(), doPost(), or both methods of this class. This class contains a default implementation of service() that calls the appropriate doXXX() method, depending on the type of request that is received.

  • ServletRequest This interface defines an object that contains the information that the client has provided, along with his request to run the servlet. A concrete implementation of this object is ServletRequestWrapper class.

  • HttpServletRequestWrapper This is an extension of the ServletRequestWrapper that contains information specifically assuming that the request will be in HTTP format. In most servlets, this class is accessed polymorphically via a handle to the ServletRequest interface. See Chapter 7, "Inheritance," for information on how this works.

  • ServletResponse This interface defines a convenient way for a servlet to communicate the information that it wants to send to the client to the servlet container. A concrete implementation of this object is ServletResponseWrapper class.

  • HttpServletResponseWrapper This is an extension of the ServletResponseWrapper that assumes that the response will be in HTTP format. In most servlets, this class is accessed polymorphically via a handle to the ServletResponse interface.

Programming Generic Servlets

Even though most of this chapter will deal with HTTP-based servlets, it is useful to understand how a servlet can be created that is not tied to this protocol. Listing 21.1 shows a simple generic servlet.

Listing 21.1 The GenericHello Class
 /*   * GenericHello.java   *   * Created on June 21, 2002, 5:28 PM   */  import javax.servlet.*;  import java.io.*;  /**   *   * @author  Stephen Potts   * @version   */  public class GenericHello extends GenericServlet  {      /** Initializes the servlet.       */      public void init(ServletConfig config) throws ServletException      {          super.init(config);       }      /** Destroys the servlet.       */      public void destroy()      {      }      public void service(ServletRequest req, ServletResponse resp)      throws ServletException, java.io.IOException      {          resp.setContentType("text/html");          java.io.PrintWriter out = resp.getWriter();          out.println("Hello from the GenericHello Servlet");          out.close();      }      /** Returns a short description of the servlet.       */      public String getServletInfo()      {          return "This servlet tests the GenericServlet class";      }  } 

Notice that this class extends the GenericServlet class. As discussed previously, this is a protocol-neutral servlet class.

 public class GenericHello extends GenericServlet 

The init() method is overridden here. Notice that it is passed a ServletConfig class, which it passes along to the super(GenericServlet) class's init() method. The ServletConfig class contains references to the servlet name and the ServletContext object. For now, we can ignore these objects.

 public void init(ServletConfig config) throws ServletException  {      super.init(config);  } 

We override the destroy() method just for show.

 public void destroy()  {  } 

We also override the getServletInfo() method so that you will have an example of how this is done.

 public String getServletInfo()  {      return "This servlet tests the GenericServlet class";  } 

Finally, the service() routine is where the action is, what little there is in this example.

 public void service(ServletRequest req, ServletResponse resp)  throws ServletException, java.io.IOException  {      java.io.PrintWriter out = resp.getWriter();      out.println("Hello from the GenericHello Servlet");      out.close();  } 

We create a handle to the response object's PrintWriter object so that we can send some information to the client. We are not interested in any of the information available from the client in this simple example. We print a string to this object, and then close it. The servlet container is responsible for actually getting the string to the client.

Deploying the Servlet

Under JDK 1.4, all the classes needed to compile this program are automatically installed. This makes it simple to compile the program. You just type the following at a command line:

 javac GenericHello.java 

The servlet is now compiled into a .class file in this same directory. If this were a garden-variety Java application, we could run it by typing the following:

 java GenericHello  Exception in thread "main" java.lang.NoSuchMethodError: main 

Being a servlet, this class has no main() method, and the Java runtime engine points that out to you by throwing an exception.

We could just go and type the name of this servlet in the address line of our browser, but that will give us an error message stating that the servlet container doesn't know anything about this servlet as shown in Figure 21.4.

Figure 21.4. . The Tomcat server doesn't know anything about this servlet, so it provides a polite error message.

graphics/21fig04.gif

We have a servlet container running, and we have a servlet that compiles. What we need is a way to tell the servlet container about this servlet. A good quick-hitter approach to this is to place the servlet in the ...\webapps\examples\WEB-INF\classes directory. After that is done, we can type the following URL in your browser's address field (with Tomcat running):

 http://localhost:1776/examples/servlet/GenericHello 

If you installed Tomcat using the default port of 8080, you would substitute "8080" for the "1776."

The examples string indicates that the GenericHello class is a servlet, and that its class file can be found under the examples subdirectory. Figure 21.5 shows the result of running GenericHello.

Figure 21.5. . The GenericServlet's output contains no formatting information.

graphics/21fig05.gif

Notice that the message is output to the screen in whatever font the browser chooses. This is done because we provided no input to the browser on how to format the results. This desire to have more control over the layout is the motivation for creating the HTTPServlet class.

Next, let's modify our example to use the HTTPServlet class so that we can have more control over the output. Listing 21.2 shows the code for the new servlet.

Listing 21.2 The HTTPHello Example
 /*   * HTTPHello.java   *   * Created on June 21, 2002, 9:59 AM   */  import javax.servlet.*;  import javax.servlet.http.*;  /**   *   * @author  Stephen Potts   * @version   */  public class HTTPHello extends HttpServlet  {      /** Initializes the servlet.       */      public void init(ServletConfig config) throws ServletException      {          super.init(config);       }      /** Destroys the servlet.       */      public void destroy()      {      }      /** Processes requests for both HTTP <code>GET</code>       *  and <code>POST</code> methods.       * @param request servlet request       * @param response servlet response       */      protected void processRequest(HttpServletRequest request,                                      HttpServletResponse response)       throws ServletException, java.io.IOException {          response.setContentType("text/html");          java.io.PrintWriter out = response.getWriter();          out.println("<html>");          out.println("<head>");          out.println("<title>HTTPHello</title>");          out.println("</head>");          out.println("<body>");          //Make the font large          out.println("<H1>");          //Make the font bold          out.println("<B>");          out.println("Hello from the HTTPHello Servlet");          out.println("</H1>");          out.println("</B>");          out.println("</body>");          out.println("</html>");          out.close();      }      /** Handles the HTTP <code>GET</code> method.       * @param request servlet request       * @param response servlet response       */      protected void doGet(HttpServletRequest request,                                HttpServletResponse response)      throws ServletException, java.io.IOException {          processRequest(request, response);       }      /** Handles the HTTP <code>POST</code> method.       * @param request servlet request       * @param response servlet response       */      protected void doPost(HttpServletRequest request,                                 HttpServletResponse response)      throws ServletException, java.io.IOException {          processRequest(request, response);      }      /** Returns a short description of the servlet.       */      public String getServletInfo() {          return "This is the HTTPHello Servlet";      }  } 

This servlet was created using the Forte for Java code editor, which generates an empty HTTPServlet for you. This can save you time when writing servlets, but it can retard learning. Until you become familiar with the purpose of every line of code in this example, any tools will hamper learning. After you can write servlets in your sleep, the tools will speed up your coding a little.

Notice that we now have an extra import statement. This package will give us HTTP processing.

 import javax.servlet.http.*; 

This servlet extends HTTPServlet. This will impact us because we will be overriding doGet() and doPost() instead of service().

 public class HTTPHello extends HttpServlet 

We have overridden the doGet() and doPost() methods in a unique fashion.

 protected void doGet(HttpServletRequest request,                               HttpServletResponse response)  throws ServletException, java.io.IOException  {      processRequest(request, response);  }  protected void doPost(HttpServletRequest request,                               HttpServletResponse response)  throws ServletException, java.io.IOException  {      processRequest(request, response);  } 

In both cases we simply made a call to a method that we named processRequest() and passed the request and response objects to it. There is nothing special about the name processRequest(). We could have called it xyz(). Later in this chapter we will look at the HTTP protocol and the difference between the Get and Post commands.

The real work in our example is now done in the processRequest() method. This method is passed in both an HttpServletRequest object and an HTTPServletResponse object.

 protected void processRequest(HttpServletRequest request,                                        HttpServletResponse response)  throws ServletException, java.io.IOException { 

These will be used extensively in future examples, but for now, we only use the response object.

 response.setContentType("text/html");  java.io.PrintWriter out = response.getWriter(); 

We use the PrintWriter object to put data into the response object for transmission back to the client. Notice that HTML code makes up the contents of the string.

 out.println("<html>");  out.println("<head>");  out.println("<title>HTTPHello</title>");  out.println("</head>");  out.println("<body>"); 

We add this line to make the font large.

 out.println("<H1>"); 

This line makes the font bold.

 out.println("<B>"); 

This line contains the contents of what we want displayed.

 out.println("Hello from the HTTPHello Servlet"); 

The result of running this is similar to when we ran the GenericHello servlet, as shown here in Figure 21.6.

Figure 21.6. The HTTPServlet enables us to format our output by using HTML commands.

graphics/21fig06.gif

Understanding HTTP

Because you will be using HttpServlet class to implement most of the servlets that you will ever write, it is important for you to understand what HTTP is. HTTP stands for Hypertext Transfer Protocol. A protocol is simply a published agreement between clients and servers that specifies what data, and its syntax, will be passed from one party to the other.

HTTP is an application layer protocol, which means that it depends on lower-layer protocols to do much of the work. In the case of HTTP, this lower-layer protocol is TCP/IP. The information in HTTP is transferred as plain ASCII characters. Plain text is convenient for programmers because the instructions are human-readable. By contrast, binary protocols like those used in RMI and CORBA are much more difficult to decipher when searching for the cause of a programming error.

HTTP is a stateless and connectionless protocol. Stateless means that each request and response pair constitutes an entire conversation. There is no memory of one transaction available to the next transaction. It is kind of like computerized amnesia. Connectionless means that there is no concept of a logon or logoff in HTTP, as there is in FTP. In fact, the requester is anonymous from the protocol's point of view.

Being stateless is both good and bad. It is good from a performance standpoint because there is no need for the program that accepts HTTP requests (the Web server) to remember any state information. This greatly reduces the server's workload and makes it possible for one server to process thousands of clients. On the other hand, being stateless limits the usefulness of the protocol. If you want to create an application that does some work, asks the user some questions, then does some more work, you have to manage this in the code that you write. We will cover this problem of saving state later in the chapter.

A connectionless protocol also has positives and negatives. If no time is spent establishing a connection, the server can service more requests per unit of time. This also limits the usefulness of the protocol. If you want a user to logon, do some stuff, then logoff, you will have to write your own code to do that. Fortunately, the servlet classes support this requirement pretty well.

HTTP is a request and response protocol. This means that it is composed of pairs of requests and responses, as shown in Figure 21.7.

Figure 21.7. . The HTTP protocol is based on the assumption that every request will be answered with one response.

graphics/21fig07.gif

The format of the request is all done in plain text and is sent as a string from the client to the server. The server reads the message and performs the task that it has been instructed to do. In some cases, this task is to retrieve a static document and send it back to the client's browser for display. In other cases, this request is for a servlet to be run and the results of that, if any, to be sent to the client.

The GET Command

The most frequently used HTTP command is the GET command. This command states that the browser is to ask the server to send back a copy of a document. If that document has already been cached, the browser might use that one instead of retrieving it again. Listing 21.3 shows a simple HTTP GET request for a document.

Listing 21.3 A Request for xyz.html
 GET /xyz.html HTTP/1.0  User-Agent: Mozilla/4.51 (WinNT; I)  Accept: image/gif, image/jpeg, image/pjpeg, */* 
  • The GET means that we want to retrieve a result. Also those parameters, if any, will be appended to the name of the document or servlet.

  • The User-Agent tag tells the server what version of the browser the client is running. This gives the server a chance to tailor the response to suit this browser.

  • The Accept tag tells the server what kind of replies, in addition to text, the browser can process.

The job of the Web server is to parse this text and decide how to handle the results. If you want to pass parameters to the server, you can do that by appending them to the name of the document, as shown in Listing 21.4.

Listing 21.4 Passing Parameters with GET
 GET /xyz.html?myparm=hello&myotherparm=world HTTP/1.0  User-Agent: Mozilla/4.51 (WinNT; I)  Accept: image/gif, image/jpeg, image/pjpeg, */* 

In this listing, we are telling the server to return that HTML page modified by the values in the parameters. The special syntax using the ? tells the server that parameters start here. A parameter/value pair is indicated by the =. The & indicates that another parameter follows this. Notice that there are no quotes around the strings. If numbers are placed on the line, they are sent as strings also, and it is up to the server or servlet to do any conversion or casting to another data type.

The parameters modify the behavior of the document or servlet. The nature of the modification is a decision of the page designer or servlet programmer. The names of the parameters are important because they will be used to extract the value for this parameter from the request object in the servlet.

There is a limit of 255 characters that can be used to pass parameters appended in this way. The reason for this is that some Web servers store this string in an environment variable that is rather small. If you use a length greater than 255, it may or may not work, depending on the client. In practice, if there is a parameter list that long, the programmer will use the POST command instead.

Another drawback of passing the parameters this way is that they appear in the address bar of the browser. If your password is one of the data items, this could be a problem because the history kept by your browser now contains your password in plain text.

Calling a servlet is very similar. Listing 21.5 contains the HTTP message to invoke a servlet:

Listing 21.5 Calling a Servlet
 GET /xyz.html?myparm=hello&myotherparm=world HTTP/1.0  User-Agent: Mozilla/4.51 (WinNT; I)  Accept: image/gif, image/jpeg, image/pjpeg, */* 

Notice that we don't specify the name of the server in this command. This is because a socket to this machine has already been opened before this message is sent. Notice also that there is no special syntax to indicate that this is a servlet. It is the responsibility of the Web server to figure out what kind of request it has been given.

The POST Command

The POST command is used to send data to the Web server. By convention, POST requests are not answered out of cache, but rather sent to the server every time. Listing 21.6 contains an example of a post command.

Listing 21.6 The POST Command
 POST /xyz.html HTTP/1.0  User-Agent: Mozilla/4.51 (WinNT; I)  Accept: image/gif, image/jpeg, image/pjpeg, */*  Content-Length: 34  Content-Type:application/x-www-form-urlencoded  myparm=hello&myotherparm=world 

Notice that there is a blank line between the header and the contents of the message; this is required. The length must also be passed as well as a content type. There is no stated limit to the length of the parameters to be passed using the POST command. In addition, the values of the parameters are not displayed on the command line of the browser. Aside from these differences, the behavior of the GET and the POST commands are identical.

The Other Commands

The HEAD command is like a GET command that returns only the header, but not the contents of the response. This can be useful if the browser wants only information about the document, but it doesn't have much practical value for servlet development. Other commands such as PUT, DELETE, LINK, and UNLINK are in the specification, but because they have little or no value to the servlet developer, we will not cover them here.

HTTP 1.1

A new version, HTTP 1.1, has been proposed and published by the Internet Engineering Task Group (IETF). This new version will add quite a few improvements to the HTTP 1.0 standard, but none that directly impact servlet developers. One improvement that indirectly impacts developers is the fact that connections are now kept alive by default. This means that the server will discontinue its conversation with the client, but without actually closing the connection. This connection can be reused, but it is not associated with the client that used it last. This behavior changes the performance, but not the syntax, of the HTTP commands.

Programming HTTP

The browser is a program that processes HTTP commands, among other things. The Web server is also an HTTP processing program. Both of these programs fill a place in our programming world, but they are not the only ways to process HTTP commands.

You can write a fairly simple pair of Java programs that communicate with each other, with browsers, and with servers using HTTP. Understanding how they work will clarify many points that are sometimes fuzzy when dealing with browsers and Web servers. Listing 21.7 shows a simple Java program that is able to talk to the Tomcat server using port 1776.

Listing 21.7 The HTTPFetch Class
 /*   * HTTPFetch.java   *   * Created on June 18, 2002, 2:54 PM   */  import java.io.*;  import java.net.*;  /**   *   * @author  Stephen Potts   * @version   */  public class HTTPFetch  {     /** Creates new HTTPFetch */      public HTTPFetch()     {     }     public static void main (String[] args)     {        try        {           URL url = new URL(           "http://localhost:1776");           BufferedReader in = new BufferedReader(                       new InputStreamReader(url.openStream()));           String line;           while ((line = in.readLine()) != null)           {              System.out.println(line);           }           in.close();        }catch(Exception e)        {            e.printStackTrace();        }     }  } 

This program simply initiates communication with the Tomcat server and receives the default home page. This is the page that was shown in Figure 21.3.

This program makes heavy use of the HTTP processing built into Java. We first declare a new URL object and pass in the address of the Tomcat server as a parameter to the constructor.

 URL url = new URL(  "http://localhost:1776"); 

Next, we open the URL's inputStream in a Buffered reader.

 BufferedReader in = new BufferedReader(              new InputStreamReader(url.openStream()));  String line; 

Finally, we look through it and write each line to the screen.

          while ((line = in.readLine()) != null)           {              System.out.println(line);  } 

To run this program, you type the following at the command line, not in a browser:

 java HTTPFetch 

Instead of displaying this page in a nice graphical format, as a browser would, this program just writes the code to standard output as shown here.

 <!doctype html public "-//w3c//dtd html 4.0 transitional//en"   "http://www.w3.org/TR/REC-html40/strict.dtd">  <html>      <head>      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">      <title>Jakarta Project - Tomcat</title>      <style type="text/css">        <!--         body {              color: #000000;              background-color: #FFFFFF;              font-family: Arial, "Times New Roman", Times;              font-size: 16px;          }          A:link {              color: blue          }          A:visited {              color: blue          }          td {              color: #000000;              font-family: Arial, "Times New Roman", Times;              font-size: 16px;          }          .code {              color: #000000;              font-family: "Courier New", Courier;              font-size: 16px;          }        -->      </style>  </head>  <body>  <!-- Header -->  <table width="100%">      <tr>          <td align="left" width="130"><a href=  "http://jakarta.apache.org/tomcat/index.html"><img src="tomcat.gif" height="92" width="130" border="0" alt=  "The Mighty Tomcat - MEOW!"></td>  .  .  .  

Because of its length, only the first part of the output is displayed here, and that part is formatted to fit on this page. This program is similar to a browser's view source command.

The second part of this example is the HTTPServer program shown here in Listing 21.8.

Listing 21.8 The HTTPServer Class
 /*   * HTTPServer.java   *   * Created on June 18, 2002, 3:07 PM   */  import java.io.*;  import java.net.*;  /**   *   * @author  Stephen Potts   * @version   */   public class HTTPServer  {     /** Creates new HTTPServer */      public HTTPServer()     {     }     public static void main(String[] args)     {        try        {           ServerSocket sSocket = new ServerSocket(1777);           System.out.println("Created the socket");           while (true)           {              System.out.println("Waiting for a client...");              Socket newSocket = sSocket.accept();              System.out.println("accepted the socket");              OutputStream os = newSocket.getOutputStream();              BufferedReader br = new BufferedReader(              new InputStreamReader(newSocket.getInputStream()));              String inLine = null;              while (((inLine = br.readLine()) != null)              && (!(inLine.equals(""))))              {                 System.out.println(inLine);              }              System.out.println("");              StringBuffer sb = new StringBuffer();              sb.append("<html>\n");              sb.append("<head>\n");              sb.append("<title>Java Primer Plus\n");              sb.append("</title>\n");              sb.append("</head>\n");              sb.append("<body>\n");              sb.append("<H1>HTTPServer Works!</H1>\n");              sb.append("</body>\n");              sb.append("</html>\n");              String string = sb.toString();              //Put the output into a byte array              byte[] byteArray = string.getBytes();              //add some header information              os.write("HTTP/1.0 200 OK\n".getBytes());              os.write(new String(               "Content-Length: "+ byteArray.length + "\n").getBytes());              os.write("Content-Type: text/html\n\n".getBytes());              //add the output              os.write(byteArray);              os.flush();              //close it up              os.close();              br.close();              newSocket.close();           }//while        }catch(Exception e)        {           e.printStackTrace();        }     }//main  }//class 

This program is another very simple TCP/IP sockets program. The first thing that we do is create the socket:

 ServerSocket sSocket = new ServerSocket(1777);  System.out.println("Created the socket"); 

Notice that we used a different port number because we have Tomcat on 1776, and we don't want a conflict. We loop and wait for a communication from a client on port 1777.

 while (true)  {     System.out.println("Waiting for a client...");     Socket newSocket = sSocket.accept();     System.out.println("accepted the socket"); 

When we get a communication from that port, we will create a handle to the socket that the client has handed us, and call it newSocket. We will use it to send information back to the client.

 OutputStream os = newSocket.getOutputStream(); 

From this point on, the program acts like any other Java IO program. We get the InputStream from the client.

 BufferedReader br = new BufferedReader(  new InputStreamReader(newSocket.getInputStream())); 

We echo the information that the client sends us to standard output.

 String inLine = null;  while (((inLine = br.readLine()) != null)  && (!(inLine.equals(""))))  {     System.out.println(inLine);  }  System.out.println(""); 

We then create some HTML code and put it in a StringBuffer.

 StringBuffer sb = new StringBuffer();  sb.append("<html>\n");  sb.append("<head>\n");  sb.append("<title>Java Primer Plus\n");  sb.append("</title>\n");  sb.append("</head>\n");  sb.append("<body>\n");  sb.append("<H1>HTTPServer Works!</H1>\n");  sb.append("</body>\n");  sb.append("</html>\n"); 

We transform it to a String object, and then to a byteArray so that the OutputStream can accept it.

 String string = sb.toString();  //Put the output into a byte array  byte[] byteArray = string.getBytes(); 

Next, we add the HTTP header information.

 os.write("HTTP/1.0 200 OK\n".getBytes()); 

We add the Content-Length.

 os.write(new String(  "Content-Length: "+ byteArray.length + "\n").getBytes()); 

We add the Content-Type.

 os.write("Content-Type: text/html\n\n".getBytes()); 

Next, we add the HTML that we wrote earlier.

 os.write(byteArray);  os.flush(); 

Finally, we close up shop.

 //close it up  os.close();  br.close();  newSocket.close(); 

Run this server by typing the following:

 java HTTPServer 

It pauses at the Waiting for a client ... until a client tries to connect. Open a browser and type the following:

 http://localhost:1777/ 

Note that a Web server doesn't need to be running for this to work. This program is its own server.

 Created the socket  Waiting for a client... 

Action by the browser causes this server to receive the following communication:

 accepted the socket  GET / HTTP/1.1  Host: localhost:1777  User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.1)   Gecko/20020508 Netscape6/6.2.3  Accept: text/xml, application/xml, application/xhtml+xml,   text/html;q=0.9, image/png, image/jpeg, image/gif;q=0.2,   text/plain;q=0.8, text/css, */*;q=0.1  Accept-Language: en-us  Accept-Encoding: gzip, deflate, compress;q=0.9  Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66  Keep-Alive: 300  Connection: keep-alive  Waiting for a client... 

You end this program by typing Ctrl-c.

We see that the browser issued a GET. We also see that the browser didn't stipulate which document to return. The server has to decide what to do in this case. Normally, commercial servers return index.html.

We see that the browser message is in HTTP 1.1. We also see that it was a Netscape 6.2.3 browser. We also see several more pieces of information that we could make use of if we were writing a fancy server. At the end, it loops back and waits for a client. The server responds to this request by stuffing the HTTP commands that we created into the OutputStream that the client sent to us. The result is displayed on the screen, as shown in Figure 21.8.

Figure 21.8. The HTTP protocol is sent to the browser that displays it.

graphics/21fig08.gif

We can see that the browser had no trouble receiving and understanding this communication. If we run the HTTPFetch command against the HTTPServer command, we can see the details of what the HTTPServer returned. All that we have to do is change the port number in the HTTPFetch program to 1777, and we are ready.

 URL url = new URL("http://localhost:1777"); 

Open a second command window and type

 java HTTPFetch 

The result will now be output to the screen.

 <html>  <head>  <title>Java Primer Plus  </title>  </head>  <body>  <H1>HTTPServer Works!</H1>  </body>  </html> 

Note

graphics/01icon18.gif

If you understand this section on HTTP, you will be in a great position to comprehend what is happening behind the scenes when your servlets are running.



       
    Top
     



    Java 2 Primer Plus
    Java 2 Primer Plus
    ISBN: 0672324156
    EAN: 2147483647
    Year: 2001
    Pages: 332

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net