20.01.2013

JSPs mit JSTL

In diesem Artikel wird kurz beschrieben, wie eine JSP-Seite aufgebaut ist und wie sie mit Hilfe der JSTL verbessert werden kann. Dies wird an dem "bekannten" Beispiel eines Einkaufswagens (Shopping-Cart) erklärt. Dieser Artikel ist keine Einführung in die JSP-Programmierung. Er soll vielmehr zeigen, wie die grundlegende Funktionsweise von JSP-Seiten ist. In den folgenden Artikeln zum Thema Java EE6 Web-Client werden andere Technologien vorgestellt, um einfacher Web-Oberflächen und Web-Clients zu erstellen.

Die fertige Anwendung, die in diesem Artikel erstellt wird, sieht im Browser folgendermaßen aus:

Auf der linken Seite lassen sich in dem Textfeld Artikelbezeichnungen eintragen und über die ComboBox wird eine Menge von 1 bis 5 ausgewählt. Mit dem Button Hinzufügen wird der Artikel in den Warenkorb gelegt und in einer Liste oberhalb angezeigt. Mit dem Button Warenkorb leeren werden alle Artikel aus dem Warenkorb entfernt und die Liste wird nicht mehr angezeigt.

Die folgende Abbildung zeigt den Ablauf einer Anfrage an den Web-Container und die Antwort an den Client.

Man sieht, dass ein Request vom Browser, in dem der Web-Client läuft, an den Web-Container, in dem ein Servlet läuft, gestellt wird. Das Servlet dient in diesem Kontext als Controller und arbeitet die Business-Logik ab. Dann wird das Erstellen der Antwort an die JSP-Seite weitergeleitet. Die View, die der Web-Container an den Browser als Response zurückgeliefert, wird also durch das Verarbeiter der JSP-Seite erstellt. Dazu wird im Gegensatz zu dem Beispiel JSP-Seite die JSTL verwendet. Als Response wird eine fertige HTML-Seite an den Browser gesendet.

Der zugehörige Java-Quellcode sieht dann folgendermaßen aus:

package org.hameister.shoppingcarts;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author hameister
 */
@WebServlet(name = "CartJSPJSTL", urlPatterns = {"/CartJSPJSTL"})
public class CartJSPJSTL extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

            //Get items in Cart for the Session
            HttpSession session = request.getSession();
            List<String> items = (List<String>)session.getAttribute("items");
            if(items == null) {
                items = new ArrayList<String>();
                session.setAttribute("items", items);
            }

            // Reset Cart
            String reset = request.getParameter("reset");
            if(reset!=null) {
                items.clear();
            }


            String name = request.getParameter("item");
            if(name != null) {
                String quantity = request.getParameter("quantity");
                //Add item to list
                items.add(quantity+" &times; "+name);
            }
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("jspjstlcart.jsp");
        requestDispatcher.forward(request, response);
    }


    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Im Vergleich zum JSP-Beispiel ändert sich beim Einsatz der JSTL also nichts am Servlet. (Beschreibung des Quelltextes findet man im JSP-Artikel)

Die passende JSP-Seite zu dem CartJSPJSTL-Servlet sieht folgendermaßen aus:

<%--
    Document   : jspjstlcart.jsp
    Created on : 08.12.2012, 09:19:05
    Author     : hameister
--%>

<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>

<%--
 Taglib hinzufuegen
--%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Shopping Cart</title>
    </head>
    <body>
        <c:choose>
            <c:when test="${not empty items}">
                <h2>Artikel im Warenkorb:</h2>
                <ul>
                    <c:forEach items="${items}" var="item">
                        <li>${item}</li>
                    </c:forEach>
                </ul>
            </c:when>
        </c:choose>


        <strong>Artikel zum JSP-JSTL-Warenkorb hinzufügen:</strong><br/><br/>
        <% // Add button %>
        <form method="POST" action="CartJSPJSTL" >
            <input type="text" name="item" >
            <select name="quantity" size="1">
                <option selected>1</option>
                <option>2</option>
                <option>3</option>
                <option>4</option>
                <option>5</option>
            </select>
            <input type="submit" value="Hinzufügen" >
        </form>

        <% // Reset button %>
        <form method="POST" action="CartJSPJSTL" >
            <input type="submit" name="reset" value="Warenkorb leeren" >
        </form>

    </body>
</html>

Gleich am Anfang ist zu sehen, dass durch die Anweisung @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" die JSTL-Taglib in die JSP-Seite eingefügt wird, so dass sie verwendet werden kann. Für for-Schleifen und if-Bedingungen werden nun entsprechende xml-Anweisungen und kein Java-Code mehr verwendet.

Hier wird der Unterschied zu der JSP-Seite in dem Artikel JSP-Beispiel deutlich. Der XML-Code ist erheblich übersichtlicher und es wird nicht zwischen Java und XML/HTML hin und her gewechselt. Dadurch ist diese JSP-Seite durch den Einsatz der JSTL erheblich leichter zu pflegen und zu erweitern.

Weitere Informationen

Weitere Informationen zu Web-Clients findet man in den folgenden Artikeln:

  1. Einleitung - Teil 1
  2. Servlets - Teil 2
  3. JSP-Seiten - Teil 3
  4. JSP-Seiten mit JSTL - Teil 4
  5. JSF-Seiten - Teil 5
  6. JSF-Seiten mit Ajax - Teil 6
  7. JSF-Templates - Teil 7