Advanced   Java   Services Servlet Basics Back Next Up Home


Lebenszyklus eines Servlets

Ein Servlet kann nur in einem ServletContainer leben. Dieser steuert den ganzen Lebenszyklus eines Servlets. Die folgende Graphik erläutert die Hauptaufgaben des ServletContainers

ServletLifeCycle.jpg

Ähnlich wie ein Applet eine Unterklasse von java.awt.Applet ist (sein muß), so muß ein Servlet das Inteface javax.servlet.Servlet implementieren. Meist stützt man sich jedoch auf die beiden abstrakten Klassen GenericServlet bzw. HttpServlet, weil diese schon eine Teilimplementierung liefern und leitet daher das eigene Servlet von GenericServlet oder von HttpServlet ab. Aufgaben eines Servlet ist es, Anfragen eines Client zu beantworten. Dazu dient die Methode service, die der Servletcontainer zu einem Servletobjekt ruft, falls eine Anfrage an das Servlet den Server erreicht. Um diese Methode aufrufen zu können generiert der ServletContainer jeweils ein Objekt vom Typ ServletRequest und ServletResponse. Dem ServletRequestObjekt wird dabei die Anfrage des Client übergeben, sodaß die service-Methode darauf objektorientiert zugreifen kann. In der service()-Methode wird dann das mitübergebene ServletResponseObjekt mit der Antwort "gefüllt", die dann nach Beendigung der Methode dem Servletcontainer zur Verfügung steht.

Verwenden die Clientanfragen immer HTTP als Protokoll, so wird man das eigene Servlet als Ableitung von HttpServlet realisieren, wogegen man durch Ableiten von GenericServlet auf jedes Protokoll reagieren kann.

Die folgenden Graphiken erläutern das Design von Servlet, bzw. ServletRequest bzw. ServletResponse.


Das Interface Servlet und sein Umfeld
ServletHierarchien1.jpg

Das Interface ServletRequest und sein Umfeld
ServletHierarchien2.jpg

Das Interface ServletResponse und sein Umfeld
ServletHierarchien3.jpg


Aufbau eines Servlets als Ableitung von GenericServlet
public class SkeletonServlet extends GenericServlet
{
   // wird gerufen von super.init(ServletConfig config)
   public void init()
      throws ServletException
   {
      // to do : initialization
   }

   public void service(ServletRequest req, ServletResponse res)
      throws ServletException
   {
      // to do : reacting on the request
   }

   public void destroy()
   {
      // cleanup, release resources
   }

ServletConfig und ServletContext

Wie bei einem Applet legt man Initialisierungen nicht in den Konstruktor, sondern in eine init() Methode. Bei der ersten Anforderung des Servlets instantiiert der ServletContainer ein Objekt von diesem Typ und ruft die init()-Methode. Der ServletContainer ruft jedoch nicht die oben erwähnte init()-Methode, sondern die init()-Methode, der er ein Objekt vom Typ ServletConfig übergibt. Da jedoch GenericServlet dieses Interface implementiert, braucht man keine eigene Instanz vom Typ ServletConfig. Man sieht jedoch aus nachstehendem Quelltext von GenericServlet, daß man über ServletConfig einen Zeiger auf einen ServletContext erhält. Sowohl ServletConfig als auch ServletContext werden vom ServletContainer angelegt und geliefert. Über ServletConfig kann man Parameter aus der web.xml auslesen, über den ServletContext kann man Information über andere Servlets erhalten und mit diesen Daten austauschen.


Sourcecode von GenericServlet
package javax.servlet;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
{
   private transient ServletConfig config;

   public GenericServlet()
   {
   }

   public void init()
      throws ServletException
   {
   }

   public void init(ServletConfig servletconfig)
      throws ServletException
   {
      config = servletconfig;
      log("init");
      init();
   }

   public void destroy()
   {
      log("destroy");
   }

   public ServletConfig getServletConfig()
   {
      return config;
   }

   // --------------- begin: von ServletConfig geforderte Methoden --------------- \\
   public String getInitParameter(String s)
   {
      return getServletConfig().getInitParameter(s);
   }

   public Enumeration getInitParameterNames()
   {
      return getServletConfig().getInitParameterNames();
   }

   public String getServletName()
   {
      return config.getServletName();
   }

   public ServletContext getServletContext()
   {
      return getServletConfig().getServletContext();
   }
   // --------------- end: von ServletConfig geforderte Methoden --------------- \\

   public String getServletInfo()
   {
      return "";
   }

   public void log(String s)
   {
      getServletContext().log(getServletName() + ": " + s);
   }

   public void log(String s, Throwable throwable)
   {
      getServletContext().log(getServletName() + ": " + s, throwable);
   }

   public abstract void service(ServletRequest servletrequest, ServletResponse servletresponse)
   throws ServletException, IOException;
}

Wie man aus dem Quellcode erkennt, reicht es, die init()-Methode ohne Parameter zu überschreiben. Es ist zudem sicherer, denn beim Überschreiben der anderen init()-Methode besteht die Gefahr, daß man den super-Aufruf vergißt. In diesem Fall erhält die Membervariable config keinen Wert und man kann weder auf ServletConfig noch auf ServletContext zugreifen.


Die Realisierung der abstrakten Klassen und Interfaces

Wer implementiert diese abstrakte Klassen und Interfaces? Es gibt nur eine Möglichkeit und die heißt ServletContainer. Es folgen einige Realisierungen am Beispiel Tomcat 5.

(Abstrakte) Klasse oder Interface Realisierung durch Tomcat 5
ServletRequest org.apache.coyote.tomcat5.CoyoteRequestFacade
ServletResponse org.apache.coyote.tomcat5.CoyoteResponseFacade
BufferedReader org.apache.coyote.tomcat5.CoyoteReader
PrintWriter org.apache.coyote.tomcat5.CoyoteWriter
ServletInputStream org.apache.coyote.tomcat5.CoyoteInputStream
ServletOutputStream org.apache.coyote.tomcat5.CoyoteOutputStream
ServletContext org.apache.catalina.core.ApplicationContextFacade
ServletConfig org.apache.catalina.core.StandardWrapperFacade
HttpSession org.apache.catalina.session.StandardSessionFacade


CGI Umgebungsvariablen und korrespondierende Servletmethoden

Zum Auslesen der CGI-Umgebungsvariablen existieren eine ganze Reihe von Methoden, die entweder in ServletRequst oder in HttpServletRequst vereinbart sind. Die folgende Tabelle zeigt, mit welchen Methoden man in einem Servlet auf die CGI-Umgebungsvariablen zugreifen kann.

CGI-Umgebungsvariable Methode Interface
AUTH_TYPE String getAuthType() HttpServletRequst
CONTENT_LENGTH int getContentLength() ServletRequest
CONTENT_TYPE String getContentType() ServletRequest
HTTP_ACCEPT String getHeader("Accept") HttpServletRequest
HTTP_REFERER String getHeader("Referer") HttpServletRequest
HTTP_USER_AGENT String getHeader("User-Agent") HttpServletRequest
PATH_INFO String getPathInfo() HttpServletRequest
PATH_TRANSLATED String getPathTranslated() HttpServletRequst
QUERY_STRING String getQueryString() HttpServletRequst
REMOTE_ADDR String getRemoteAddr() ServletRequst
REMOTE_HOST String getRemoteHost() ServletRequst
REMOTE_USER String getRemoteUser() HttpServletRequest
REQUEST_METHOD String getMethod() HttpServletRequest
SERVER_NAME String getServerName() ServletRequst
SERVER_PORT int getServerPort() ServletRequst
SERVER_PROTOCOL String getProtocol() ServletRequst
SERVER_SOFTWARE String getServerInfo() ServletContext

top Back Next Up Home