Servlet
Willemers Informatik-Ecke
HttpURLConnection Java Server Pages JSP

Bei der Client-Server-Programmierung kann man sich auf die Socket-Ebene zurückziehen und alles selbst programmieren und auch das Protokoll selbst festzulegen. Die Alternative ist ein Application-Server wie Glassfish oder Tomcat, der als Protokoll HTTP verwendet und den „technischen Kram“ übernimmt.

Um die Clientanfragen inhaltlich zu bearbeiten, ruft der Application Server ein Servlet auf. Ein Servlet ist ein Java-Programm-Modul, das die Anfrage des Clients liest und eine Antwort zusammensetzt.

Ein Client für HTTP kann mit einer HttpURLConnection erstellt werden.

Servlets sind die Basiskomponenten bei der Programmierung von Jakarta/Java Enterprise Edition. Die anderen Technologien wie Java Server Pages (JSP), Java Server Faces (JSF), SOAP oder REST setzen darauf auf.

Für die Erstellung von Servlets benötigt man eine Entwicklungsumgebung, die einen Application-Server in die IDE einbindet.

Die Klassen Servlet und HttpServlet

In der Regel arbeiten Servlets auf der Basis des Protokolls HTTP. Darum erweitert ein Servlet die Klasse HttpServlet, welche ihrerseits die Klasse Servlet erweitert.

Vom Interface Servlet erbt ein Servlet die Methoden init und destroy, die es polymorph überschreiben kann. Die Methode init wird beim ersten Start des Servlets aufgerufen und die Methode destroy, wenn das Servlet entfernt wird.

Die Methode getServletConfig kann die Konfiguration auslesen. Die Methode init erhält als Parameter das Objekt der Klasse ServletConfig, das vom Application Server für das Servlet angefertigt wurde. Es enthält Informationen aus der Konfigurationsdatei web.xml, die Eclipse freundlicherweise automatisch erstellt hat.

Die Methode getServletInfo ermittelt den Info-String.

Bei Anfragen von einem Client wird die Methode service aufgerufen. Sie liefert in ihren Parametern alle Informationen zur Anfrage (request)und den Ausgabekanal (response).

void service(ServletRequest request, ServletResponse response)
             throws ServletException, IOException;
In der Regel verwendet ein Servlet HTTP und darum erweitert es die Klasse HttpServlet, die ihrerseits das Interface Servlet implementiert.

Die Klasse HttpServlet stellt statt der Methode service Methoden zur Auswertung von HTTP-Kommandos zur Verfügung. Am häufigsten werden doPost zur Reaktion auf POST-Anfragen, doGet für GET-Anfragen überschrieben, seltener auch doPut für PUT und doDelete für DELETE. Alle diese Methoden haben die gleichen Parameter wie service.

Erstellen eines Servlets mit Eclipse

Unter Eclipse können Sie den Rahmen eines Servlets automatisch erstellen. Zunächst benötigen Sie ein Projekt für den Application-Server, ein Dynamic Web Project: In diesem Projekt kann ein Servlet angelegt werden. Eclipse erstellt dann einen Servlet-Rahmen:
@WebServlet("/GetForm")
public class GetForm extends HttpServlet {
    public GetForm() {
        super();
    }

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) 
                   throws ServletException, IOException {
        response.getWriter().append("Served at: ")
                            .append(request.getContextPath());
    }

    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) 
                   throws ServletException, IOException {
        doGet(request, response);
    }
}
Damit das Servlet in Aktion kommt, muss ein Client erstellt werden. Das geht aber zum Glück relativ einfach. Wir erstellen eine HTML-Seite mit einem FORM, das das Servlet aufruft.

Ein HTML-Formular erstellen

Bei der Erstellung einer HTML-Datei kann Eclipse helfen. Die erstellte Datei befindet sich im Projekt unter dem Ordner WebContent. Im Editor erscheint der Rahmen einer HTML-Seite. Hinter den Tag <body> setzen wir folgende Zeilen ein:
<form action=GetForm method=get>
  <input type=submit value="Start">
</form>
Auf dem Browser erscheint:
Served at: /TestServlet

Datenverkehr und Parameter

Wir erweitern nun die HTML-Seite und fügen zwei Eingabefelder hinzu. Diese sollen nun per POST an das Servlet gelangen, das diese auslesen soll und eine Tabelle als Ergebnis vorweisen soll.
<form action="GetForm" method="post">
  <table> <tr>
      <td>Name</td>
      <td><input type=text name=user value="" size=30 /></td>
    </tr> <tr>
      <td>E-Mail</td>
      <td><input type=text name=email value="" size=30 /></td>
    </tr> <tr>
      <td><input type=submit value="Einfügen" /></td>
      <td></td> </tr> </table>
</form>
Jetzt können wir das Servlet aufbohren, so dass doPost das Formular ausliest und den Inhalt an den Client zurücksendet.
protected void doPost(HttpServletRequest request,
                     HttpServletResponse response)
               throws ServletException, IOException {

    response.getWriter().append("<!DOCTYPE html>\n<html><body>" +
                "Benutzer: " + request.getParameter("user") +
                " E-Mail: " + request.getParameter("email") +
                "<p/><a href=\"TestServlet.html\">zurück</a>" +
                "</body></html>");
}
In den HTML-Code wurde noch ein kleiner Link geschummelt, der zum wiederholten Ausprobieren auf die Eingabeseite zurückführt.

Ein Blick auf die Parameter HttpServletRequest und HttpServletResponse

HttpServletRequest request

Über den Parameter request kann die Umgebung des Aufrufs ausgelesen werden. Die folgende Methode liest alle FORM-Parameter aus der request und erzeugt eine HTML-Tabelle mit allen Eingabeelementen und ihren Inhalten.
protected void doPost(HttpServletRequest request,
                      HttpServletResponse response)
               throws ServletException, IOException {
    response.getWriter().println("<table>");
    // Hole alle Parameterbezeichner
    Enumeration<String> controls = request.getParameterNames();
    while (controls.hasMoreElements()) {
        String controlName = controls.nextElement();
        // Zeige den Parameterbezeichner
        response.getWriter().println("<tr><td>" + controlName);
        // Zeige den eingegeben Wert
        response.getWriter().println("</td><td>"
                 + request.getParameter(controlName) + "</td></tr>");
    }
    response.getWriter().println("</table>");
}

HttpServletResponse response

Über den Parameter response wird der Zugriff auf die Antwort an den Client eröffnet.

Internes Dispatchen

Der Aufruf von response.sendRedirect gibt die Meldung über die Antwort (response) an den Client weiter, sich an eine andere URL zu wenden. Das Servlet kann den Auftrag aber auch intern an ein anderes Servlet weiterleiten, indem es über die Anfrage-Variable (request) einen Request-Dispatcher auslöst.
RequestDispatcher dispatch = request.getRequestDispatcher("anzeige.jsp");
dispatch.forward(request, response);
In diesem Zusammenhang kann es von Interesse sein, Attribute der request mit setAttribute zu hinterlegen. Diese können am Ziel mit getAttribute ausgelesen werden.
request.setAttribute("name", strName);
// ...
String str = request.getAttribute("name");

Projektstruktur

Die Struktur eines dynamischen Webprojekt hat in Eclipse folgendes Aussehen:
+ TestServlet
  + Java Ressources
  |     Hier stecken die Java-Quelltexte, also die Servlets
  ...
  + WebContent
    + META-INF
    + WEB-INF
    | + web.xml
    | + lib    (für Libraries)
    index.html
    TestServlet.html

HttpSession

HTTP-Kommunikation kennt eigentlich keine Sessions, die aber gebraucht werden, um beispielsweise einen Einkauf über mehrere Seiten zu verfolgen.

Allerdings stellt das Servlet eine einfache Lösung zur Verfügung. Aus dem Request-Parameter kann mit der Methode getSession die aktuelle Session ermittelt werden. Gibt es noch keine, wird eine angelegt.

HttpSession session = request.getSession();

Sessions können mit Cookies realisiert werden, durch Erweitern der URL um eine Session-ID (insbesondere bei GET) oder durch verborgene Eingabeelemente. Standardmäßig werden Cookies verwendet.

Mit den folgenden Methoden kann der Session Werte zugeordnet werden:

Die Methoden sind überladen. Es ist möglich, Strings oder primitive Typen zu verwenden, aber auch alle Objekte, die Object erweitern (also alle). Bei getAttribute muss dabei natürlich gecastet werden, da Object zurückgegeben wird. Diese Objekte sind in der Regel JavaBeans.

Weitere Methoden des Request-Parameters

String str = request.getHeader("User-Agent");

Cookie[] cookies = request.getCookies();

InputStream in = request.getInputStream();

Links