Java™ Servlet Technologie
zurück weiter
Java™ Servlet Technologie

Anwendungsbeispiel


Das Servlet Product

Zielstellung

Das Servlet Product hat die Aufgabe, die Einzelheiten über ein Produkt im Hauptfenster des Produktkataloges darzustellen. Die Darstellung erfolgt für die Produkte eines ausgewählten Kataloges nach Betätigen des Buttons unterhalb der letzten Auswahlbox des Navigations-Fensters beziehungsweise nach Betätigung des Buttons zur Produktansicht mittels Suchfunktion über selbiges Fenster. Innerhalb des Produktfensters soll es außerdem möglich sein, zwischen den einzelnen Produkten eines Kataloges beziehungsweise einer Suchanfrage zu navigieren. Hierzu stehen zwei Button zur Verfügung, die beim Betätigen das vorhergehende beziehungsweise nachfolgende Produkt im Hauptfenster darstellen. Zur besseren Orientierung wird zusätzlich angezeigt, wie viele Produkte zur Ansicht bereit stehen und das Wievielte davon gerade betrachtet wird.

Umsetzung

Zur Umsetzung der angesprochenen Funktionalitäten muß zunächst das Servlet Product generiert werden. Hierzu wird wiederum die Klasse HttpServlet erweitert. Die Methoden zur Initialisierung eines Servlets und Beendigung eines Servlets werden hier exakt genauso benutzt, wie es auf der vorigen Seite beim Servlet Catalog beschrieben wurde. Deshalb wird an dieser Stelle nicht nochmals darauf eingegangen, sondern sofort mit der Beschreibung der Verarbeitung der Client-Anfrage begonnen.

Da der Aufruf des Servlets sowohl aus dem Navigations-Fenster (nach erfolgter Katalogauswahl beziehungsweise Aufruf der Suchfunktion) als auch aus dem Produktfenster (Navigieren zum vorhergehenden beziehungsweise nachfolgenden Produkt) heraus erfolgen kann, muß vom Servlet eine entsprechende Fallunterscheidung getroffen werden. Diese ergibt sich anhand der Auswertung verschiedener Formular-Parameter des Requests.


    // Verarbeitung der Client-Anfrage
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        // Formatierung der ermittelten Links zu den Produktbildern
        String pictures = "";
        // Formatierung von Produktgruppenname und Katalog-Hierarchie
        String[] groupPath = {"","",""};
        // zur Entgegennahme der Ergebnismenge aus Abfrage
        Vector product = new Vector();
        // akt. Produktnummer und Gesamtanzahl
        int pos = 0;
        int cnt = 0;
        // Formatierung der Navigations-Button
        String button_left = null;
        String button_right = null;

        // globale Fehlervariable
        noError = true;
        // Parameter "n_group_id" der Navigationsseite abfragen (gid)
        String group_id = request.getParameter("n_group_id");
        // wenn Anfrage nicht vom Navigations-Fenster kommt, sondern vom Produktfenster selbst
        if (group_id == null) {
            // Parameter "p_group_id" der Produktseite abfragen (gid)
            group_id = request.getParameter("p_group_id");
            if (group_id == null) group_id = "";
        }
        // Parameter "n_searchtext" der Navigationsseite abfragen (Schnellsuch-Funktion)
        String searchtext = request.getParameter("n_searchtext");
        // falls Anfrage nicht vom Navigations-Fenster stammt, sondern aus Produktfenster selbst
        // (Navigieren zwischen Produkten einer Suchabfrage)
        if (searchtext == null) {
            // Parameter "p_searchtext" der Produktseite abfragen
            searchtext = request.getParameter("p_searchtext");
            if (searchtext == null) searchtext = "";
        }
        // Parameter "p_product_id" der Produktseite abfragen (pid)
        String product_id = request.getParameter("p_product_id");
        if (product_id == null) product_id = "";
        // Parameter "p_direction" der Produktseite abfragen (voriges/folgendes Produkt)
        String direction = request.getParameter("p_direction");
        if (direction == null) direction = "0";

        // Produktdaten ermitteln mittels Methode getProduct() und Übergabe der ermittelten Parameter
        // (Methode wird nachfolgend noch genauer beschrieben)
        product = getProduct(product_id, group_id, searchtext, Integer.parseInt(direction));
        // wenn bei Ausführung von getProduct() keine Fehler aufgetreten ist
        if (noError) {
            if (product != null) {
                // wenn mindestens ein Produkt vorhanden ist
                if (product.size() > 1) {
                    // Produkt-ID des aktuellen Produktes merken
                    product_id = (String)product.elementAt(0);
                    // Gruppen-ID des aktuellen Produktes merken
                    group_id = (String)product.elementAt(8);
                    // Bilder zum Produkt mittels Methode getPicture() ermitteln
                    // (Methode wird nachfolgend noch genauer beschrieben)
                    pictures = getPicture(product_id);
                }
                else {
                    product_id = "";
                }
            }
            else product_id = "";
            // wenn bisher kein Fehler aufgetreten ist
            if (noError) {
                // Kopfzeile der Produktseite mittels der Methode getGroupPath() generieren
                // (Methode wird nachfolgend noch genauer beschrieben)
                groupPath = getGroupPath(group_id);
                // wenn bisher kein Fehler aufgetreten ist
                if (noError) {
                    if (groupPath != null) {
                        // wenn Anfrage über Suchfeld vorliegt
                        if (!searchtext.equals("")) {
                            // anstatt der Produktgruppen-Bezeichnung
                            groupPath[0] = "Ergebnis der Suchanfrage";
                        }
                    }
                    // Navigationsschaltflächen der Produktseite bzgl. Datensatzposition generieren
                    if (product != null) {
                        // wenn Produktdaten vorhanden
                        if (product.size() > 1) {
                            // aktuelle Produktnummer gemessen an der Zahl aller entsprechend der Auswahl betrachtbaren Produkte
                            pos = Integer.parseInt((String)product.elementAt(11)) + 1;
                            // Anzahl aller Produkte, die entsprechend der Auswahl betrachtet werden können
                            cnt = Integer.parseInt((String)product.elementAt(10));
                        }
                        else cnt = 0;
                    }
                    else cnt = 0;
                    // akt. Produktnummer gleich 0, wenn Gesamtzahl gleich 0
                    if (cnt == 0) pos = cnt;
                    // Schaltfläche "zurück"
                    button_left = "src=\"../images/arrow_left.jpg\"";
                    // wenn nicht gerade das 1. Produkt angeigt wird
                    if (pos > 1) {
                        // Navigations-Button aktiviert
                        button_left = "<INPUT name=\"prev\" type=image " + button_left + " onClick=\"setDirection(document.frmProduct.prev.value);\">";
                    }
                    else {
                        // Navigations-Button deaktiviert
                        button_left = "<IMG " + button_left + ">";
                    }
                    // Schaltfläche "weiter"
                    button_right = "src=\"../images/arrow_right.jpg\"";
                    // wenn nicht gerade das letzte Produkt angeigt wird
                    if (pos < cnt) {
                        // Navigations-Button aktiviert
                        button_right = "<INPUT name=\"next\" type=image " + button_right + " onClick=\"setDirection(document.frmProduct.next.value);\">";
                    }
                    else {
                        // Navigations-Button deaktiviert
                        button_right = "<IMG " + button_right + ">";
                    }
                }
            }
        }

        // Erzeugung und Ausgabe der HTML-Seite mit event. Fehlerauswertung
        try {
            // wenn bei Abarbeitung kein Fehler aufgetreten ist
            if (noError) {
                // vorgefertigte HTML-Seite einlesen und Platzhalter ersetzen
                // absolute Pfadangabe muß bei Verwendung angepaßt werden
                page = pageGen.readPage("/export/pub/jakarta-tomcat-4.0.3/webapps/adia/servlets/product.html");
                page = pageGen.replaceParam(page,groupPath[0],"@group@");
                page = pageGen.replaceParam(page,groupPath[1],"@path@");
                page = pageGen.replaceParam(page,groupPath[2],"@catalog_id@");
                // Prüfung auf NULL-Wert des Objektes product
                if (product != null) {
                    // wenn Produktdaten vorhanden
                    if (product.size() > 0) {
                        page = pageGen.replaceParam(page,(String)product.elementAt(1),"@pname@");
                        page = pageGen.replaceParam(page,(String)product.elementAt(9) + " " + (String)product.elementAt(5),"@price@");
                        page = pageGen.replaceParam(page,(String)product.elementAt(2),"@description@");
                        page = pageGen.replaceParam(page,(String)product.elementAt(7),"@articlenr@");
                        page = pageGen.replaceParam(page,(String)product.elementAt(3),"@item@");
                        page = pageGen.replaceParam(page,(String)product.elementAt(4),"@itemprice@");
                        page = pageGen.replaceParam(page,(String)product.elementAt(6),"@producer_id@");
                    }
                }
                // bei nicht vorhandenen Produktdaten Platzhalter entfernen
                else {
                    page = pageGen.replaceParam(page,"","@pname@");
                    page = pageGen.replaceParam(page,"","@price@");
                    page = pageGen.replaceParam(page,"","@description@");
                    page = pageGen.replaceParam(page,"","@articlenr@");
                    page = pageGen.replaceParam(page,"","@item@");
                    page = pageGen.replaceParam(page,"","@itemprice@");
                    page = pageGen.replaceParam(page,"","@producer_id@");
                }
                // Platzhalter ersetzen
                page = pageGen.replaceParam(page,pictures,"@picture@");
                page = pageGen.replaceParam(page,product_id,"@product_id@");
                page = pageGen.replaceParam(page,group_id,"@group_id@");
                page = pageGen.replaceParam(page,searchtext,"@searchtext@");
                page = pageGen.replaceParam(page,button_left,"@button_left@");
                page = pageGen.replaceParam(page,button_right,"@button_right@");
                page = pageGen.replaceParam(page,String.valueOf(pos),"@position@");
                page = pageGen.replaceParam(page,String.valueOf(cnt),"@count@");
            }
            // falls während Abarbeitung ein Fehler aufgetreten ist
            else {
                // absolute Pfadangabe muß bei Verwendung angepaßt werden
                page = pageGen.readPage("/export/pub/jakarta-tomcat-4.0.3/webapps/adia/servlets/error.html");
                page = pageGen.replaceParam(page,error,"@error@");
            }
        }
        // falls beim Laden der vorgefertigten Seite oder beim Ersetzen der Platzhalter ein Fehler auftritt
        catch (Exception e) {
            page = e.toString();
        }
        // generierte Seite an Client senden
        out.println(page);
    }
    
Die vorgefertigte HTML-Seite mit den Platzhaltern kann hier betrachtet werden.

Im folgenden sollen nun die drei Methoden des Servlets Product beschrieben werden, die in der zuvor beschrieben doGet(HttpServletRequest request, HttpServletResponse response)-Methode nicht näher beschrieben wurden. Als erstes wäre da die Methode getGroupPath(String group_id). Sie ermittelt die Produktgruppen-Bezeichnung und den hierarchischen Pfad zur angegebenen Gruppen-ID. Der Rückgabewert dieser Methode dient der Ersetzung der Platzhalter @group@, @path@ und @catalog_id@ der vorgefertigten HTML-Seite und gibt nach außen hin einen aufgetretenen Fehler zu erkennen, falls er dem NULL-Wert entspricht. Außerdem wird beim Auftreten eines Fehlers auch die globale Fehlervariable noError mit dem Wahrheitswert FALSE belegt. Im nachfolgenden Auszug des Quell-Codes wird dies genauer beschrieben.


    // Ermittlung von Produktgruppe und Produktpfad
    private String[] getGroupPath(String group_id) {
        String[] groupPath = {"","",""};
        String tmp_id = group_id;
        String arrow = "";
        int typnr = 0;
        // Pfad zur Wurzel hin verfolgen und Abspeichern sowie untersten Gruppennamen merken,
        // falls gültige Gruppen-ID vorhanden
        if (!group_id.equals("")) {
            try {
                do {
                    // Parameterliste für Datenbankabfrage initialisieren
                    String[] param = {"NAME","MUTTERGRUPPE_ID","TYPNR","CID"};
                    // Datenbankabfrage durchführen
                    Vector result = dbcon.OraDBgetResult("SELECT name,muttergruppe_id,typnr,cid FROM struktur WHERE gid=" + tmp_id, param, 0);
                    // wenn Abfrage keine leere Ergebnismenge zurückgeliefert hat
                    if (result != null) {
                        // Gruppen-ID der übergeordneten Ebene merken
                        tmp_id = (String)result.elementAt(1);
                        // Typnummer merken (kennzeichnet Hierarchie)
                        typnr = Integer.parseInt((String)result.elementAt(2));
                        // wenn nicht bereits die Wurzel vorliegt
                        if (typnr != 1 && typnr != 4) arrow = " > "; else arrow = "";
                        // aktuelle Gruppe an eventuell bereits vorhandenen Pfad vorn anfügen
                        groupPath[1] = arrow + "<U>" + (String)result.elementAt(0) + "</U>" + groupPath[1];
                        // wenn erster Durchlauf dieser Schleife (unterste Ebene in aktueller Katalog-Hierarchie)
                        if (groupPath[0].equals("")) {
                            // Name der Produktgruppe abspeichern
                            groupPath[0] = (String)result.elementAt(0);
                            // zugehörige Katalog-ID (cid) abspeichern
                            groupPath[2] = (String)result.elementAt(3);
                        }
                    }
                    // Abbruch bei leerer Ergebnismenge der Abfrage kenntlich machen
                    else {
                        typnr = 0;
                    }
                // solange kein Abbruch, Wurzelkatalog oder nicht hierarchisch gegliederter Katalog vorliegt
                } while (typnr != 0 && typnr != 1 && typnr != 4);
            }
            // Fehlerbehandlung
            catch (SQLException e) {
                noError = false;
                groupPath = null;
                error = e.toString();
            }
        }
        // Ergebnis zurückgeben
        return groupPath;
    }
    
Zur Ermittlung der Produktdaten dient die Methode getProduct(String product_id, String group_id, String searchtext, int direction). Durch den bereits angesprochenen Umstand, daß der Aufruf des Servlets sowohl aus dem Navigations-Fenster (Anzeigen des ersten Produktes einer Produktgruppe bzw. entsprechend Suchanfrage) als auch aus dem Produktfenster (Navigation zwischen Produkten einer Produktgruppe oder entsprechend Suchanfrage) heraus erfolgen kann, muß hier eine entsprechende Fallunterscheidung getroffen werden. Desweiteren ist zu Unterscheiden, ob die anzuzeigenden Produkte zu einer Produktgruppe gehören, oder ob sie einem Suchbegriff entsprechen müssen. Entsprechend den hier genannten Kriterien müssen dann die Datenbankabfragen formuliert werden, um daß Ergebnis in Form eines Vector()-Objektes zurückgeben zu können. Der Rückgabewert dieser Methode gibt nach außen hin einen aufgetretenen Fehler zu erkennen, falls er dem NULL-Wert entspricht. Außerdem wird beim Auftreten eines Fehlers auch die globale Fehlervariable noError mit dem Wahrheitswert FALSE belegt. Im nachfolgenden Auszug des Quell-Codes wird das dabei angewendete Vorgehen dargestellt und durch Kommentare erläutert.

    // Produktdaten ermitteln
    private Vector getProduct(String product_id, String group_id, String searchtext, int direction) {
        Vector products = new Vector();
        Vector tmp = new Vector();
        String query1 = "";
        String query2 = "";
        String query3 = "";

        try {
            // Parameterlisten zu Datenbankabfragen initialisieren
            String[] param1 = {"PID","BEZEICHNUNG","BESCHREIBUNG","EINHEIT","PREIS_EINHEIT","WAEHRUNG","HID","HPNR","GID","PREIS"};
            String[] param2 = {"CNT"};

            // Produktdaten ermitteln
            // Abfrage zum Produkt aus Navigation-Fenster heraus
            if (product_id.equals("")) {
                // erstes Produkt für eine Produktgruppe anzeigen
                if (searchtext.equals("")) {
                    // erstes Produkt des Gesamtbestandes anzeigen
                    if (group_id.equals("")) {
                        query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND ORDER BY p.pid";
                    }
                    // erstes Produkt einer Gruppe/Untergruppe anzeigen
                    else {
                        query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.gid=" + group_id + "  ORDER BY p.pid";
                    }
                }
                // erstes Produkt entspr. Suchanfrage anzeigen
                else {
                    query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND UPPER(p.bezeichnung) LIKE UPPER('%" + searchtext + "%')  ORDER BY p.pid";
                }
            }
            // Aufruf aus Produktfenster heraus, d.h. nächstes/voriges Produkt anzeigen
            else {
                // Produkt einer Produktgruppe anzeigen
                if (searchtext.equals("")) {
                    // Produkt aus Gesamtbestand anzeigen
                    if (group_id.equals("")) {
                        // nächstes Produkte des Gesamtbestandes
                        if (direction == 1) {
                            query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.pid>" + product_id + "  ORDER BY p.pid";
                        }
                        // voriges Produkte des Gesamtbestandes
                        else {
                            query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.pid<" + product_id + "  ORDER BY p.pid DESC";
                        }
                    }
                    // Produkt einer Produktgruppe anzeigen
                    else {
                        // nächstes Produkt einer Gruppe/Untergruppe
                        if (direction == 1) {
                            query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.gid=" + group_id + " AND j.pid>" + product_id + "  ORDER BY p.pid";
                        }
                        // voriges Produkt einer Gruppe/Untergruppe
                        else {
                            query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.gid=" + group_id + " AND j.pid<" + product_id + "  ORDER BY p.pid DESC";
                        }
                    }
                }
                // Produkt entspr. Suchanfrage anzeigen
                else {
                    // nächstes Produkt entspr. Suchanfrage
                    if (direction == 1) {
                        query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND UPPER(p.bezeichnung) LIKE UPPER('%" + searchtext + "%') AND j.pid>" + product_id + "  ORDER BY p.pid";
                    }
                    // voriges Produkt entspr. Suchanfrage
                    else {
                        query1 = "SELECT p.*, j.gid, j.preis FROM produkt p, join_g_p j WHERE p.pid=j.pid AND UPPER(p.bezeichnung) LIKE UPPER('%" + searchtext + "%') AND j.pid<" + product_id + "  ORDER BY p.pid DESC";
                    }
                }
            }

            // Queries zum Zählen der Datensätze und der aktuellen Datensatznummer generieren
            // Produktanzahl und Position entspr. Produktgruppe oder Gesamtbestand
            if (searchtext.equals("")) {
                // Produktanzahl und Position des Gesamtbestandes
                if (group_id.equals("")) {
                    // Gesamtzahl
                    query2 = "SELECT COUNT(pid) cnt FROM produkt";
                    // dient der Berechnung der aktuellen Position gemessen an Gesamtzahl
                    query3 = "SELECT COUNT(pid) cnt FROM produkt WHERE pid<";
                }
                // Produktanzahl und Position einer Produktgruppe
                else {
                    // Gesamtzahl
                    query2 = "SELECT COUNT(j.pid) cnt FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.gid=" + group_id;
                    // dient der Berechnung der aktuellen Position gemessen an Gesamtzahl
                    query3 = "SELECT COUNT(j.pid) cnt FROM produkt p, join_g_p j WHERE p.pid=j.pid AND j.gid=" + group_id + " AND j.pid<";
                }
            }
            // Produktanzahl und Position entspr. Suchanfrage
            else {
                // Gesamtzahl
                query2 = "SELECT COUNT(pid) cnt FROM produkt WHERE UPPER(bezeichnung) LIKE UPPER('%" + searchtext + "%')";
                // dient der Berechnung der aktuellen Position gemessen an Gesamtzahl
                query3 = "SELECT COUNT(pid) cnt FROM produkt WHERE UPPER(bezeichnung) LIKE UPPER('%" + searchtext + "%') AND pid<";
            }

            // Queries ausführen
            products = dbcon.OraDBgetResult(query1, param1, 1);
            // wenn Ergebnismenge nicht leer, dann Position und Gesamtanzahl ermitteln
            if (products != null) {
                // Gesamtanzahl ermitteln
                tmp = dbcon.OraDBgetResult(query2, param2, 1);
                // wenn Ergebnismenge nicht leer, dann Wert zur Berechnung edr Position ermitteln
                if (tmp != null) {
                    // Gesamtanzahl abspeichern
                    products.addElement(tmp.elementAt(0));
                    // wenn gültige Gesamtanzahl
                    if (!((String)products.elementAt(0)).equals("")) {
                        // query3 um aktuelle Produkt-ID ergänzen
                        query3 += (String)products.elementAt(0);
                        // Agfrage ausführen
                        tmp = dbcon.OraDBgetResult(query3, param2, 1);
                        // wenn Ergebnismenge nicht leer
                        if (tmp != null) {
                            // ermittelten Wert abspeichern
                            products.addElement(tmp.elementAt(0));
                        }
                        else products.addElement("0");
                    }
                    else products.addElement("0");
                }
            }
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            noError = false;
            products = null;
            error = e.toString();
        }
        // Ergebnis zurückgeben
        return products;
    }
    
Die Methode getPicture(String product_id) generiert schließlich eine Tabelle im HTML-Format, deren Inhalt aus Links zu den Produktbildern besteht. Als Parameter muß dieser Methode die entsprechende Produkt-ID zur Ermittlung der Links per Datenbankabfrage übergeben werden. Der Rückgabewert dieser Methode dient der Ersetzung des Platzhalters @picture@ der vorgefertigten HTML-Seite und gibt nach außen hin einen aufgetretenen Fehler zu erkennen, falls er dem NULL-Wert entspricht. Außerdem wird beim Auftreten eines Fehlers auch die globale Fehlervariable noError mit dem Wahrheitswert FALSE belegt. Nachfolgend ein Auszug aus dem Quell-Code, der diese Methode genauer beschreibt.

    // Generierung einer HTML-Tabelle mit den Links zu den Produktbildern
    private String getPicture(String product_id) {
        Vector pictures = new Vector();
        Vector tmp = new Vector();
        String result = "";

        try {
            // parameterliste zur Datenbankabfrage initialisieren
            String[] param1 = {"QUELLE"};
            // Abfrage ausführen
            tmp = dbcon.OraDBgetResult("SELECT quelle FROM bilder WHERE pid=" + product_id, param1, 0);
            // falls kein Bild für Produkt vorhanden ist
            if (tmp == null) {
                // Standardbild zuweisen
                pictures.addElement("../images/no_pic.jpg");
            }
            // Bildinformationen (Links) zuweisen
            else {
                pictures = tmp;
            }
            // Ergebnismenge ins HTML-Tabellenformat umwandeln
            String[] param2 = {"","","<IMG src=\"","\" width=300>"};
            result = pageGen.formatTable(pictures, 1, param2);
        }
        // Fehlerbehandlung
        catch (SQLException e) {
            noError = false;
            error = e.toString();
            result = null;
        }
        // Ergebnis zurückgeben
        return result;
    }
    

zurück weiter