Java Servlets

Ein Servlet ist ein Java-Programm, das serverseitig läuft und typischerweise HTML Code generiert, der an den Browser als Antwort auf einen Request zurückgeschickt wird. Daneben kann es auch andere Operationen geben, wie z.B. Datenbank- und Dateizugriffe.

Das Servlet ist keine eigenständige Applikation (hat keine main() Methode), sondern kann nur innerhalb eines Containers laufen. Als Container werden verschiedene Server verwendet, u.a. das jserv Modul des Apache-Webservers, sowie Tomcat (am Schulungsraumserver, Version 5.0.14, Nov 2003).

Gegenüber der klassischen CGI-Lösung sind kürzere Antwortzeiten möglich, weil nicht bei jedem Request serverseitig ein neuer Prozeß gestartet werden muß. Aufwendige Operationen können einmalig ablaufen (z.B. beim ersten Request an eine bestimmte Applikation) und dann für weitere Requests zur Verfügung stehen, z.B. der Verbindungsaufbau zu einer Datenbank. Mit Session Attributes können serverseitig Werte gespeichert werden und damit auf einfache Art Warenkörbe und ähnliches implementiert werden.


Konfiguration und Verzeichnisse

Auf dem Schulungsraumserver balrog.wu-wien.ac.at ist Tomcat installiert. Tomcat Web Applikationen bestehen aus HTML Seiten und Java Servlets. Dabei ist folgende Verzeichnis-Struktur ubd Konfiguration zu beachten ($HOME steht für das home directory, z.B. /home/j8325200):

*.html in $HOME/webapp
*.class in $HOME/webapp/WEB-INF/classes
*.java in $HOME/webapp/src
web.xml in $HOME/webapp/WEB-INF. Wird vom Skipt web-xml erzeugt, das Sie immer starten, wenn Sie ein neues Servlet geschrieben haben.
URL auf HTML: z.B. http://balrog.wu-wien.ac.at:8080/j8325200/index.html
URL auf Servlets: z.B. http://balrog.wu-wien.ac.at:8080/j8325200/servlet/Hello

Hilfreich: ein Makefile im src/ Verzeichnis. Nach jeder Änderung der .java Dateien wird mit dem Befehl 'make' neu kompiliert und die .class Datei ins WEB-INF/classes Verzeichnis gestellt.


Servlet Programmierung

Im Servlet werden zunächst zumindest io, servlet und servlet.http importiert.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
Die Servlet Klasse gehört zu HttpServlet und enthält die doGet und/oder die doPost Methode.
public class Hello extends HttpServlet {
    protected void doGet(HttpServletRequest req,
                         HttpServletResponse res) {
Ausgaben gehen über den PrintWriter aus dem Resultat.
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    out.println("....");

Hello Servlet

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Hello extends HttpServlet {
    protected void doGet(HttpServletRequest req,
                         HttpServletResponse res)
              throws ServletException, IOException {
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    out.println("<HTML><HEAD><TITLE>Hello!</TITLE>"+
                "</HEAD><BODY>Hello, its j8325200!</BODY></HTML>");
    out.close();
  }
}

Select Servlet

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;

public class Select extends HttpServlet {
  PrintWriter out;

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    res.setContentType("text/html");
    out = res.getWriter();
    klist();
  }

  void klist () {
    String url = "jdbc:oracle:thin:@balrog:1521:aidb2";
    String userName = "j8325200";
    String password = "...";
    try {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn = DriverManager.getConnection (url, userName, password);
      Statement stmt = conn.createStatement ();
      ResultSet rset = stmt.executeQuery ("select NR, NAME from KUNDE");
      out.print("<HTML><BODY><TABLE>");
      while (rset.next ()) {
        out.println ("<TR><TD>" + rset.getString("NR") 
          + "<TD>" + rset.getString("NAME"));
      }
    } catch (SQLException e) {
      out.print("Caught SQLException!");
    }
    out.print("</TABLE></BODY></HTML>");
    out.close();
  }
}

Insert

Zum Daten erfassen verwenden wir HTML-Formulare, deren action Parameter auf das Insert-Servlet zeigt. Dort können wir dann mit req.getParameter() bestimmte Parameter aus dem HTML-Formular abfragen.

Die HTML-Formulare (z.B. Insert.html) kommen ins webapp/ Verzeichnis am balrog-Rechner, d.h. die gesamte Applikation wird mit dem Tomcat-Server betrieben. Auch die Startseite Ihres Online-Shops sollte dort sein. Der URL dorthin lautet z.B. http://balrog.wu-wien.ac.at:8080/jMatNr/Shop.html

Im Servlet verwenden Sie statt doGet die doPost() Methode, damit die Daten nicht über den URL mitgegeben werden.

public class Insert extends HttpServlet {
  PrintWriter out;

  public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    String nr = req.getParameter("NR");
    String name = req.getParameter("NAME");
    String adresse = req.getParameter("ADRESSE");
    ...

und so weiter wie gehabt. Hier steht dann das SQL-Insert, das natürlich wieder mit Hilfe von Exceptions auf Fehler Rücksicht nehmen muß.


Insert Servlet

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;

public class Insert extends HttpServlet {
  PrintWriter out;
  public void doPost(HttpServletRequest req, HttpServletResponse
res)
    throws ServletException, IOException {
    String nr = req.getParameter("NR");
    String name = req.getParameter("NAME");
    String adresse = req.getParameter("ADRESSE");
    res.setContentType("text/html");
    out = res.getWriter();
    String url = "jdbc:oracle:thin:@balrog:1521:aidb2";
    String userName = "j8325200";
    String password = "j8325200";
    try {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn = DriverManager.getConnection (url, userName, password);
      Statement stmt = conn.createStatement();
      ResultSet rset = stmt.executeQuery(
        "insert into KUNDE (nr, name, adresse)"
        + " values(" + nr + ", \'" + name + "\', \'" + adresse + "\')");
      out.print("OK.");
    } catch (SQLException e) {
      out.print("FEHLER!! SQLException: " + e.getMessage());
    }
    out.close();
  }
}

Session Attribute

Mit Java Servlets können serverseitig Werte gespeichert werden, die mit einer Browser-Sitzung verbunden sind. Diese session attributes sind nützlich, um Dinge wie Login-Information oder Warenkörbe auf einfache Art zu implementieren.

Jede Session hat ein ID:

    HttpSession session = req.getSession(true);
    String id = session.getId();
    out.print("session id = " + id);

Ein Attribut kann gesetzt werden:

    try {
      session.setAttribute("s", "Mozilla");
      out.print("setting session Attribute s = " + "Mozilla");
    } catch (Exception e) {
      out.print("Error setting session Attribute!");
    }

Und abgefragt werden:

    try {
      String s = session.getAttribute("s").toString();
      out.print("getting session attribute s = " + s);
    } catch (Exception e) {
      out.print("Error getting session attribute!");
    }

Session Servlet - Attribut Setzen

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Session extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
    HttpSession session;
 
    res.setContentType("text/html");
    res.setHeader("pragma", "no-cache");
    PrintWriter out = res.getWriter();

    session = req.getSession(true);
    String id = session.getId();
    out.print("session id = " + id);

    try {
      session.setAttribute("s", "Mozilla");
      out.print(", setting session Attribute s = " + "Mozilla");
    } catch (Exception e) {
      out.print("Error setting session Attribute!");
    }
    out.close();
  }
}

Ausprobieren


Session2 Servlet - Attribut Abfragen

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Session2 extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
    HttpSession session;
 
    res.setContentType("text/html");
    res.setHeader("pragma", "no-cache");
    PrintWriter out = res.getWriter();

    session = req.getSession(true);
    String id = session.getId();
    out.print("session id = " + id);

    try {
      String s = session.getAttribute("s").toString();
      out.print(", getting session attribute s = " + s);
    } catch (Exception e) {
      out.print("Error getting session attribute!");
    }
    out.close();
  }
}

Ausprobieren


File Upload

HTML Formular:


<form action=/.../servlet/FileUp method=POST ENCTYPE="multipart/form-data">
...
<input type=file name=...>

Servlet FileUp.java:

import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import java.io.*;
import java.util.*;

public class FileUp extends HttpServlet {
  PrintWriter out = null;

  public void doPost(HttpServletRequest req, HttpServletResponse res) {
    res.setContentType("text/html");
    String file = req.getParameter("file");
    try {
      out = res.getWriter();
      DiskFileUpload fu = new DiskFileUpload();
      List fileItems = fu.parseRequest(req);
      Iterator i = fileItems.iterator();
      String content = ((FileItem)i.next()).getString();
      out.println("File Upload: " + content);
    } catch (Exception e) {
      out.println("Error: " + e);
    }
  }
}

Zum Kompilieren:
export CLASSPATH=$CLASSPATH:/usr/local/tomcat-5.0.18/server/lib/commons-fileupload-1.0.jar
(am besten in ~/.bash_profile)
Siehe auch: jakarta.apache.org


Aufgabe

Nun haben wir alle technischen Hilfsmittel, um eine einfache Warenwirtschaft entsprechend dem Modell am Schluß des Kapitels ER-Modell zu implementieren. Die Stammdatenpflege für Artikel und Kunden sowie die Auftragsverwaltung sollen über das Web möglich sein. Achten Sie bei der Umsetzung auf:

Zusatzaufgaben:

Offenlegung gem. 25 MedienG