Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5
Java ist auch eine Insel

Java ist auch eine Insel
5., akt. und erw. Auflage
1454 S., mit CD, 49,90 Euro
Galileo Computing
ISBN 3-89842-747-1
gp Kapitel 17 Servlets und Java Server Pages
  gp 17.1 Dynamische Web-Seiten und Servlets
    gp 17.1.1 Was sind Servlets?
    gp 17.1.2 Was sind Java Server Pages?
    gp 17.1.3 Vorteil von JSP/Servlets gegenüber CGI-Programmen
  gp 17.2 Vom Client zum Server und wieder zurück
    gp 17.2.1 Der bittende Client
    gp 17.2.2 Welche Form von Antwort erzeugt ein Web-Server?
    gp 17.2.3 Wer oder was ist MIME?
  gp 17.3 Servlets und JSPs entwickeln und testen
    gp 17.3.1 Servlet-Container
    gp 17.3.2 Web-Server mit Servlet-Funktionalität
  gp 17.4 Java Server Pages in Tomcat und Eclipse
    gp 17.4.1 Download und Installation
    gp 17.4.2 Ablageort für eigene JSP-Seiten
    gp 17.4.3 Web-Applikationen
    gp 17.4.4 Zuordnung von Web-Applikationen zu physikalischen Verzeichnissen
  gp 17.5 Skript-Elemente
    gp 17.5.1 Scriptlets
    gp 17.5.2 Ausdrücke
    gp 17.5.3 Deklarationen
    gp 17.5.4 Kommentare
    gp 17.5.5 Quoting
    gp 17.5.6 Entsprechende XML-Tags
  gp 17.6 Implizite Objekte
  gp 17.7 Was der Browser mit auf den Weg gibt – HttpServletRequest
    gp 17.7.1 Verarbeiten der Header
    gp 17.7.2 Hilfsfunktion im Umgang mit Headern
    gp 17.7.3 Übersicht der Browser-Header
  gp 17.8 Formulardaten
  gp 17.9 Das HttpServletResponse-Objekt
    gp 17.9.1 Automatisches Neuladen
    gp 17.9.2 Seiten umlenken
  gp 17.10 JSP-Direktiven
    gp 17.10.1 page-Direktiven im Überblick
    gp 17.10.2 include-Direktive
    gp 17.10.3 Mit JSPs Bilder generieren
  gp 17.11 Aktionen
    gp 17.11.1 Aktion include
    gp 17.11.2 Aktion forward
    gp 17.11.3 Aktion plugin
  gp 17.12 Beans
    gp 17.12.1 Beans in JSP-Seiten anlegen, Attribute setzen und erfragen
    gp 17.12.2 Der schnelle Zugriff auf Parameter
  gp 17.13 Kleine Kekse: die Klasse Cookies
    gp 17.13.1 Cookies erzeugen und setzen
    gp 17.13.2 Cookies vom Servlet einlesen
    gp 17.13.3 Kleine Helfer für Cookies
    gp 17.13.4 Cookie-Status ändern
    gp 17.13.5 Langlebige Cookies
  gp 17.14 Sitzungsverfolgung (Session Tracking)
    gp 17.14.1 Das mit einer Sitzung verbundene Objekt HttpSession
    gp 17.14.2 Werte mit einer Sitzung assoziieren und auslesen
    gp 17.14.3 URL-Rewriting
    gp 17.14.4 Zusätzliche Informationen
  gp 17.15 Tag-Libraries
    gp 17.15.1 Standard Tag Library (JSTL)
    gp 17.15.2 Jakarta Taglibs Project
  gp 17.16 Servlets
    gp 17.16.1 Servlets compilieren
    gp 17.16.2 Die Servlets in das classes-Verzeichnis
    gp 17.16.3 Servlet-Mapping
  gp 17.17 Der Lebenszyklus eines Servlets
    gp 17.17.1 Initialisierung in init()
    gp 17.17.2 Abfragen bei service()
    gp 17.17.3 Mehrere Anfragen beim Servlet und die Thread-Sicherheit
    gp 17.17.4 Das Ende eines Servlets
  gp 17.18 Das HttpServletResponse-Objekt
    gp 17.18.1 Wir generieren eine Web-Seite
    gp 17.18.2 Binärdaten senden
    gp 17.18.3 Noch mehr über Header, die der Server setzt
  gp 17.19 Objekte und Dateien per POST verschicken
    gp 17.19.1 Datei-Upload
  gp 17.20 Servlets und Sessions
  gp 17.21 Weiterleiten und Einbinden von Servlet-Inhalten
  gp 17.22 Inter-Servlet-Kommunikation
    gp 17.22.1 Daten zwischen Servlets teilen
  gp 17.23 Internationalisierung
    gp 17.23.1 Die Länderkennung des Anfragers auslesen
    gp 17.23.2 Länderkennung für die Ausgabe setzen
    gp 17.23.3 Westeuropäische Texte senden
  gp 17.24 Tomcat: Spezielles
    gp 17.24.1 Tomcat als Service unter Windows NT ausführen
    gp 17.24.2 Interessante Links zum Thema Servlets/JSP


Galileo Computing

17.13 Kleine Kekse: die Klasse Cookiedowntop

Jeder Auftrag an den Web-Server wird unabhängig von anderen Aufträgen verwaltet. Wenn wir beispielsweise eine Seite neu laden oder einen Verweis verfolgen, weiß der Server nicht (beziehungsweise interessiert sich nicht dafür), dass die Anfrage von uns kam. Was an diesem Verhalten deutlich wird, ist das Fehlen eines Zustands. Es fehlt also die Möglichkeit, dass ein Client vom Server identifiziert wird und einem aktuellen Zustand des bidirektionalen Kommunikationsverlaufes zugeordnet werden kann. Der Zustand bezieht sich hier auf eine nicht-existente Server-seitige Information. Aus diesem Grund wird HTTP auch als zustandsloses Protokoll bezeichnet. Dass dies aber nicht immer wünschenswert ist und sogar einen Nachteil darstellen kann, sehen wir an unterschiedlichen Anforderungen:

gp  Ein Warenkorb für den Einkauf In Online-Systemen wird ein Einkaufswagen gefüllt, und unterschiedliche Web-Seiten informieren Kaufwillige über die Produkte. Wenn der Server allerdings die Seitenanfrage dem Client nicht zuordnen kann, ist es nicht möglich, den Warenkorb zu füllen.
gp  Individualisierung Bei privaten Seiten muss sich ein Benutzer anmelden, um die Angebote nutzen zu können. Es ist unpraktisch, wenn er sich bei jedem Seitenwechsel neu authentifizieren muss. Verlässt ein Kunde das System auf einer bestimmten Seite, kann Ersteres nach einem erneuten Anmelden den Benutzer wieder zurück auf diese Seite führen. Hat der Kunde per Suchmaschine eine Ware gesucht, die nicht verfügbar war, kann sich dies nach einer Zeit geändert haben. Das System sollte dem Benutzer dann die Information geben, dass seine Ware nun verfügbar ist.
gp  Demoskopie Das System eignet sich auch für die Benutzerüberwachung. Besucht ein Benutzer eine Seite mehrmals, kann der Betreiber dies erkennen und diese Information mit einem »Ist-Beliebt-Faktor« verbinden. Diese Information lässt sich natürlich kommerziell gut nutzen.

Es ist also ein System gesucht, das es dem Server erlaubt, den Client zu identifizieren. Dazu dienen kleine Informationseinheiten, die Cookies. Der Server kann den Client veranlassen, diese Information eine bestimmte Zeit lang zu speichern. Betritt der Client die Seite des Anbieters, schickt er dem Server den Cookie als Kennung. Dieser kann anhand der Cookie-Kennung die Sitzung erkennen, sofern er die Information gesichert hat. Name und Technologie der Cookies wurden von Netscape geprägt, als die Firma noch den Browser-Markt revolutionierte. Mittlerweile kümmert sich die HTTP Working Group der Internet Engineering Task Force (IETF) um die Weiterentwicklung.

Das Wort »Cookie« wird gerne mit Keksen assoziiert, was aber nicht beabsichtigt ist. Informatiker kennen den Begriff und meinen damit einfach nur kleine Informationseinheiten. Mehr Informationen rund um Cookies hat David Whalen auf seiner Seite http://www.cookiecentral.com/ gesammelt.


Galileo Computing

17.13.1 Cookies erzeugen und setzen  downtop

Cookies werden für den Benutzer durch die Klasse Cookie verwaltet. Sie bietet Methoden zur Bearbeitung der Informationen, die der Cookie speichert. Damit wir auf der Client-Seite Cookies setzen können, müssen wir zunächst ein Cookie-Objekt erzeugen. Dazu bietet die Klasse genau einen Konstruktor mit zwei Parametern an, die dem Cookie einen Namen und einen Wert geben. Der Name muss nach RFC 2109 geformt sein, das heißt vereinfacht aus Buchstaben und Ziffern. Nun muss der Cookie beim Client gesetzt werden. Dies führt die Methode addCookie() auf dem HttpServletResponse-Objekt durch:

Cookie cookie = new Cookie( "key""value" );
response.addCookie( cookie );

Da es mehrere Einträge geben kann, darf die Methode auch mehrmals aufgerufen werden.


interface javax.servlet.http.  HttpServletResponse
  extends ServletResponse

gp  public void addCookie( Cookie cookie ) Fügt der Anwort einen angefüllten Cookie-Header zu.

Galileo Computing

17.13.2 Cookies vom Servlet einlesen  downtop

Bei jeder weiteren Kommunikation mit einem Server werden die mit der Server-URL assoziierten Cookie-Daten automatisch mitgeschickt. Um sie zu erfragen, bemühen wir die Methode getCookies() des HttpServletRequest-Objekts. Der Rückgabewert der Methode ist ein Feld von Cookie-Objekten. Jeder Cookie bietet als Objektmethode getName() und getValue() an, um an die Schlüssel/Werte-Paare zu gelangen. Wenn die getCookies()-Methode null liefert, so war noch kein Cookie angelegt, und wir müssen darauf reagieren.

Listing 17.17   CookieDemo.jsp

<%page import="java.util.*" %>
<%
  String myCookieName = "visisted";
  Cookie[] cookies = request.getCookies();
  if ( cookies == null )
    out.println( "Kein Cookie gesetzt!" );
  else
  {
    boolean visited = false;
    for ( int i = 0; i < cookies.length; i++ )
    {
      String cookieName = cookies[i].getName();
      if ( cookieName.equals(myCookieName) )
          visited = true;
%>
Cookie "<%= cookieName %>" hat den Wert "<%= cookies[i].getValue() %>"
<br>
<%
    }
    if ( !visited )
    {
      Cookie visCookie = new Cookie( myCookieNamenew java.util.Date().
        toString() );
      response.addCookie( visCookie );
      out.println( "Cookie gesetzt" );
    }
  }
%>

Bekommt der Server eine Anforderung vom Client, kennt der Client natürlich die Server-Adresse. Er schaut in seinem Cookie-Speicher nach, ob mit diesem Server ein Cookie assoziiert ist. Dann schickt er diesen automatisch in einem speziellen Cookie-Feld mit, sodass der Server diesen Wert auslesen kann. Cookies sind für andere Server nicht sichtbar, sodass sie keine direkte Sicherheitslücke darstellen.


Galileo Computing

17.13.3 Kleine Helfer für Cookies  downtop

Setzen wir mehrere Cookies im Programm, liefert getCookies() lediglich ein Feld von Cookie-Objekten. Wollen wir einen Keks mit einem bestimmen Namen ansprechen, so müssen wir durch das Feld wandern und nach dem Cookie suchen. Dafür bietet sich eine vorteilhafte Hilfsmethode an, die das Feld nach dem Cookie durchsucht. Wir wollen die Methode getCookieValue() nennen.

public static String
getCookieValue( Cookie[] cookiesString nameString default )
{
  for( int i = 0; i < cookies.length; i++ )
    return name.equals( cookies[i].getName()) ?
                        cookies[i].getValue() : default;
}

Diese Methode hat noch einen weiteren Vorteil: Sie übergibt dem Aufrufer einen Standardwert, falls der Cookie nicht gesetzt wurde.

Eine andere Lösung besteht darin, die Cookies in ein Map-Objekt abzulegen. Dann erfolgt die Anfrage immer aus dem Assoziativspeicher und nicht mehr aus dem Feld. Der Vorteil liegt darin, dass wir einmal die Map erstellen und dann den Cookie über die Methode get() erfragen. Das folgende Programmstück erzeugt aus dem HttpServletRequest selbstständig ein HashMap-Objekt mit den Schlüssel/Werte-Paaren:

public Map getCookies( HttpServletRequest request )
{
  Cookie[] cookies = request.getCookies();
  Map m = new HashMap();
  for ( int i = 0; i < cookies.length; i++ )
    m.put( cookies[i].getName()cookies[i].getValue() );
  return m;
}

Jetzt ist es leicht, nach einem Cookie zu fragen:

Map m = getCookies( request );
if ( !m.isEmpty() )
  String s = (String) m.get( key );

Der Test, ob Cookies überhaupt gesetzt sind, ist einfach. Dies ist ein Aufruf von m.isEmpty().


Galileo Computing

17.13.4 Cookie-Status ändern  downtop

Im Cookie werden neben einem Namen und dem damit verbundenen Wert noch weitere Informationen gespeichert. Die nachfolgende Aufzählung zeigt die Zugriffsmethoden für Cookies:


class javax.servlet.http.  Cookie
  implements java.lang.Cloneable

gp  void setComment( String purpose )
gp  String getComment() Eine zusätzliche Beschreibung für den Cookie, der nicht von jedem Browser unterstützt wird (beispielsweise von Netscape). Bei der Abfragemethode bekommen wir null, falls dem Cookie kein Kommentar zugewiesen wurde.
gp  setDomain( String pattern )
gp  String getDomain() Der Gültigkeitsbereich eines Cookies. Der Domänenname beginnt mit einem Punkt (etwa .kuchenfuerulli.com) und gilt dann für alle direkten Rechner dieser DNS-Adresse, also etwa www.kuchenfuerulli.com, aber nicht a.b.kuchenfuerulli.com.
gp  void setMaxAge( int expiry )
gp  int getMaxAge() setMaxAge() setzt das Alter in Sekunden, in denen der Cookie existieren soll. Ist der Wert negativ, wird der Cookie nicht gespeichert, sondern nach der Sitzung, also beim Schließen des Browsers, entfernt. getMaxAge() liefert die Lebensdauer eines Cookies, wobei die oben getätigten Aussagen auch hier zutreffen.
gp  void setPath( String uri )
gp  public String getPath() Der Pfad gibt den Ort für den Client an, an dem der Cookie sichtbar ist. Die Sichtbarkeit gilt für das angegebene Verzeichnis und alle Unterverzeichnisse. Zusätzliche Informationen sind in der RFC 2109 abgelegt.
gp  void setSecure( boolean flag )
gp  public boolean getSecure() Mit einer sicheren Verbindung lassen sich Cookies nur über ein sicheres Protokoll wie HTTPS oder SSL übertragen. setSecure(true) sendet den Cookie daher nur, wenn ein sicheres Protokoll verwendet wird. getSecure() liefert false, wenn der Browser den Cookie durch ein beliebiges Protokoll senden kann.
gp  void setName( String name )
gp  String getName() Der Name des Cookies, der nach der Erzeugung nicht mehr geändert werden kann.
gp  void setValue( String newValue )
gp  String getValue() Jeder Cookie speichert einen Wert, der mit setValue() neu gesetzt werden kann, sofern das Cookie existiert. Bei einem binären Wert müssen wir selbstständig eine ASCII-Kodierung finden, zum Beispiel eine BASE64-Kodierung. Mit Cookies der Version 0 sind die Zeichen ' ', '(', ')', '[', ']', '=', ',', '\'', '»', '\', '?', '@', ':', ';' nicht zugelassen. Nicht gesetzte Werte können unterschiedliche Rückgaben des Browsers provozieren.
gp  int getVersion()
gp  void setVersion( int v ) Die Version des Cookies, wie in RFC 2109 beschrieben. Version 0 hält sich an die Originalspezifikation von Netscape. Die Version 1 wird im RFC 2109 beschrieben; die Variante ist noch etwas experimentell.

Galileo Computing

17.13.5 Langlebige Cookies  toptop

Für Cookies, die länger als eine Sitzung halten sollen, lässt sich mit setMaxAge() eine Zeit setzen, zu der sie gültig sein sollen. Eine praktische Klasse ist MaxAgeCookie, die im parametrisierten Konstruktor das Alter auf die Höchstzahl von einem Jahr setzt. Dies müssen aber nicht alle Browser so implementieren.

Listing 17.18   MaxAgeCookie.java

import javax.servlet.http.*;
public class MaxAgeCookie extends Cookie
{
  public MaxAgeCookie( String nameString value )
  {
    super( namevalue );
    setMaxAge( 60*60*24*365 );
  }
}



1  Das ist richtig für das Amerikanische, die Engländer können damit meist nicht viel anfangen, dort heißt ein Keks Biscuit.

 << zurück




Copyright © Galileo Press GmbH 2005
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de