![]() |
|||||||||||||||
|
Wie auch bei Swing-Komponenten handelt es sich beim Servlet-API um ein Extension-API, also um eine Erweiterung der Java_Klassenbibliothek. Dieses API ist allerdings im Gegensatz zum Swing-API kein Standardteil von JDK in der Version 1.2. Servlets werden bei Bedarf, also während der Laufzeit des Webservers, als Java-Bytecode nachgeladen. Das einzige Bindeglied zwischen einem Servlet und einem Webserver besteht hierbei in einem speziellen API, dem Servlet-API. Dieses API ist allgemein gehalten und macht daher weder Annahmen über die Art und Weise, wie ein Servlet geladen wird, noch über die Server_Umgebung oder das Netzwerkprotokoll, mit dessen Hilfe Client und Server kommunizieren. Servlets sind daher auch nicht auf das Hypertext Transfer Protocol (HTTP) beschränkt, auch wenn dieses in den meisten Fällen zum Einsatz kommt. Beim Servlet-API handelt es sich um lediglich zwei Pakete:
Jedes Servlet implementiert das Interface javax.servlet.Servlet entweder direkt oder durch Erweiterung der abstrakten Klassen GenericServlet oder HTTPServlet, die selbst dieses Interface implementieren.
Abb. 13.5: Implementierungshierarchie eines Servlets In Tab. 13-2, Tab. 13-3 und in Tab. 13-4 sind die Klassen und Interfaces des Packages javax.servlet dargestellt. |
|||||||||||||||
|
|||||||||||||||
|
Tab. 13.2: Interfaces des Packages javax.servlet |
|||||||||||||||
|
|||||||||||||||
|
Tab. 13.3: Klassen des Packages javax.servlet |
|||||||||||||||
|
|||||||||||||||
|
Tab. 13.3: Exceptions des Packages javax.servlet Servlet-Lebenszyklus Das im Folgenden angegebene Interface Servlet deklariert die Methoden init() zur Initialisierung eines Servlets, service() zur Bedienung von Anfragen von Clients und destroy() zur Beendigung von Servlets.
public interface Servlet { public abstract void init(ServletConfig config) throws ServletException; public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public abstract void destroy(); ... }
Abb. 13.6: Lebenszyklus eines Servlets Diese Methoden, die zu verschiedenen Zeitpunkten der Lebensdauer eines Servlets aufgerufen werden, stellen den sog. Lebenszyklus eines Servlets dar. Abb. 13-6 veranschaulicht den Lebenszyklus eines Servlets. Initialisierung von Servlets Die init-Methode eines Servlets wird genau einmal aufgerufen, wenn der Byte-code des Servlets von einem Webserver geladen und eine Instanz des Servlets erzeugt wird. Dies geschieht spätestens dann, wenn die erste Abfrage eines Clients bezüglich des Servlets beim Server erfolgt. Innerhalb dieser Methode wird, wie auch bei einem Applet, die Initialisierung des Servlets vorgenommen. Eventuell benötigte Initialisierungsparameter können, analog zu der getParameter-Methode von Applets, mit der Methode getInitParameter eingelesen werden. Falls die Initialisierung aufgrund eines Fehlers nicht ordnungsgemäß durchgeführt werden kann, löst die init_Methode eine UnavailableException-Ausnahme aus. Ein Beispiel einer init-Methode ist im Folgenden angegeben.
import javax.servlet.http.*; public void init(ServletConfig config) throws ServletException { super.init(config); } Bearbeitungsphase des Servlets Nachdem die Initialisierung abgeschlossen ist, kann ein Servlet beliebig viele Abfragen bearbeiten. Ein Servlet kann nun Anfragen von Clients entgegennehmen und sie in der service-Methode bearbeiten. Da die service_Methode bei jeder Anfrage in einem eigenen Prozess (Thread) ausgeführt wird, können mehrere service-Methoden zeitlich parallel ablaufen. Die Implementierung dieser Methode sollte möglichst frei von Seiteneffekten sein. Zugriffe auf eine gemeinsam benutze Ressource dürfen daher keine Seiteneffekte auf einen anderen, parallel ablaufenden Prozess verursachen. Aus diesem Grund ist es wichtig, Zugriffe auf gemeinsame Daten innerhalb der service_Methode zu synchronisieren. Falls die service-Methode aufgrund eines Fehlers nicht ordnungsgemäß durchgeführt werden kann, löst sie eine ServletException-Ausnahme oder eine IOException-Ausnahme aus. Ein Beispiel hierfür ist im Folgenden angegeben. In diesem Beispiel werden die Header-Informationen einer HTML-Seite geladen und in einer Tabelle dargestellt.
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); String name = (String)enum.nextElement(); out.println("<td>" +value+ "</td>" ); else out.println("<td><i>Kein Wert</i></td>" ); out.println("</tr>"); } } Im Beispiel wird eine HTML-Seite dynamisch generiert. Diese Seite liest mit Hilfe der Methode getHeaderNames() alle Header-Informationen aus. Diese Informationen werden einer Tabelle hinzugefügt, die dann als Ergebnis der Abfrage an den Client zurückgesendet wird. Beenden eines Servlets Wenn ein Servlet initialisiert ist, läuft es auf dem Server und wartet so lange auf Client-Anfragen, bis es explizit beendet wird. Um ein Servlet zu beenden, muss der Webserver die destroy-Methode aufrufen. Das Beenden eines Servlets erfolgt bspw. dann, wenn der Server heruntergefahren wird oder wenn der Server explizit die Anweisung bekommen hat, das Servlet zu beenden. Beim Aufruf der destroy_Methode werden die bei der Initialisierung reservierten Ressourcen freigegeben und an die Garbage Collection übergeben. Das Servlet hat die Möglichkeit, seinen Zustand für einen erneuten Aufruf von init() zu speichern. Erfolgt nach dem Aufruf der destroy-Methode eine weitere Anfrage an das Servlet, so wird es erneut geladen und initialisiert.
public void destroy() { super.destroy(); }
Abb. 13.7: Ausgabe des HeaderSnoop-Servlets
Servlet-Beschreibung Zusätzlich zu den Aufgaben, die ein Servlet ausführen kann, kann es mit Hilfe der Methode getServletInfo Informationen über sich selbst als Ergebnis übergeben. Wird diese Methode nicht überschrieben, so liefert sie ein null-Objekt zurück. Die Servlet-Beschreibung wird als String-Objekt erzeugt, das bspw. den Autor und die Versionsnummer eines Servlets zurückliefern kann.
public String getServletInfo() { return "Header-Informationen abfragen (c) openjava 1999."; } } Werden die Code-Teile, die zur Erläuterung des Lebenszyklus von Servlets benutzt wurden, zusammengefügt, übersetzt und anschließend das entstehende Servlet aufgerufen, so ergibt sich die in Abb. 13-7 dargestellte Ausgabe. Es ist zu beachten, dass die Header-Informationen, die hier gelesen werden, Browser-abhängig sind und daher von Browser zu Browser variieren können. Konfiguration eines Servlets Das Interface ServletConfig wird implementiert, um ein Servlet konfigurieren zu können, wenn es zum ersten Mal geladen wird. Die Klasse GenericServlet implementiert dieses Interface und dementsprechend die folgenden drei Methoden:
Schnittstellen zur Servlet-Engine Das Interface Interface ServletRequest Dieses Interface wird dazu verwendet, um Informationen bzw. eine Anfrage vom Client zum Servlet zu senden. Ein Interface ServletResponse Dieses Interface wird implementiert, um MIME-Datentypen aus der Um einen MIME-Inhalt aus binären Eingabedaten zu erzeugen, wird die getOutputStream-Methode verwendet, die ein OutputStream-Objekt liefert. Um dagegen einen MIME-Inhalt aus Textdaten zu erzeugen, wird die getWriter-Methode verwendet, die ein PrintWriter-Objekt liefert. Die gleichzeitige Verwendung beider Datentypen ist hierbei ohne weiteres möglich. Das Interface ServletResponse beinhaltet folgende Methoden:
Servlet-Ausnahmen Die Servlet-Ausnahmebehandlung beinhaltet zwei Klassen: Synchronisation von Servlets Es bestehen zwei Möglichkeiten, Servlets frei von Seiteneffekten ablaufen lassen zu können: Zum einen mit dem Interface
public class ThreadSafeServlet extends Servlet { protected synchronized void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // Diese Methode ist synchronisiert } } In JSDK 2.0 wird das Interface javax.servlet.SingleThreadModel von dem jeweiligen Servlet implementiert, das frei von Seiteneffekten ablaufen soll. Die Implementierung dieser Klasse, die keine Methoden und keine Konstruktoren beinhaltet, garantiert, dass die service-Methode des Servlets niemals parallel aufgerufen werden kann:
public class ThreadSafeServlet extends Servlet implements SingleThreadModel { protected void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // Diese Methode ist automatisch durch die Implementierung } } |
|
|