Java Web Basic – Tag 7 von 10
Von Elyndra Valen, Senior Developer bei Java Fleet Systems Consulting


Include

🗺️ Deine Position im Kurs

TagThemaStatus
1Java EE Überblick & HTTP (Teil 1)✅ Abgeschlossen
2HTTP-Protokoll Vertiefung & Zustandslosigkeit✅ Abgeschlossen
3Servlets & Servlet API✅ Abgeschlossen
4Deployment Descriptor & MVC vs Model 2✅ Abgeschlossen
5JSP & Expression Languages (Teil 1)✅ Abgeschlossen
6Java Beans, Actions, Scopes & Direktiven✅ Abgeschlossen
→ 7Include-Action vs Include-Direktive👉 DU BIST HIER!
8JSTL – Java Standard Tag Libraries🔒 Noch nicht freigeschaltet
9Java Web und Datenbanken – Datasource🔒 Noch nicht freigeschaltet
10Connection Pools & JDBC in Web-Umgebungen🔒 Noch nicht freigeschaltet

Modul: Java Web Basic
Gesamt-Dauer: 10 Arbeitstage (je 8 Stunden)
Dein Ziel: Den Unterschied zwischen Include-Action und Include-Direktive verstehen und richtig anwenden


📋 Voraussetzungen für diesen Tag

Du brauchst:

  • ✅ JDK 21 LTS installiert
  • ✅ Apache NetBeans 22 (oder neuer)
  • ✅ Payara Server 6.x konfiguriert
  • ✅ Tag 1-6 abgeschlossen
  • ✅ JSP-Direktiven verstanden (<%@ page %>, <%@ include %>)
  • ✅ JSP Standard Actions kennen (<jsp:useBean>, <jsp:setProperty>)
  • ✅ Expression Language (EL) beherrschen

Tag verpasst?
Spring zurück zu Tag 6, um JSP-Direktiven und Actions zu verstehen. Das ist die Grundlage für heute!

Setup-Probleme?
Schreib uns: elyndra.valen@java-developer.online


⚡ Das Wichtigste in 30 Sekunden

Heute lernst du:

  • ✅ Was der Unterschied zwischen <%@ include file="..." %> und <jsp:include page="..." /> ist
  • ✅ Wann du welches Include verwenden solltest
  • ✅ Compile-Time vs. Runtime Includes
  • ✅ Parameter an Include-Dateien übergeben
  • ✅ Performance-Unterschiede verstehen
  • ✅ Best Practices für wiederverwendbare Komponenten

Am Ende des Tages kannst du:

  • Beide Include-Mechanismen sicher verwenden
  • Die richtige Include-Methode für verschiedene Szenarien wählen
  • Dynamische Includes mit Parametern erstellen
  • Performance-Probleme vermeiden
  • Modulare, wartbare JSP-Anwendungen bauen

Zeit-Investment: ~8 Stunden
Schwierigkeitsgrad: Mittel (viele praktische Beispiele!)


👋 Willkommen zu Tag 7!

Hi! 👋

Elyndra hier. Heute wird’s spannend – wir tauchen tief in eines der am meisten missverstandenen JSP-Themen ein!

Kurzwiederholung: Challenge von Tag 6

Gestern solltest du eine Shopping-Cart-Anwendung mit JavaBeans und Scopes erstellen. Falls du es noch nicht gemacht hast, schau dir das Beispielprojekt an – es zeigt dir Best Practices für Session-Management!

Heute geht’s um ein Detail, das riesige Auswirkungen hat:

Include-Action vs. Include-Direktive.

Klingt nach einem kleinen Unterschied? Ist es nicht!

Die Wahl zwischen <%@ include %> und <jsp:include> kann entscheiden über:

  • Performance deiner Anwendung
  • Wartbarkeit deines Codes
  • Deployment-Komplexität
  • Debugging-Schwierigkeiten

Real talk: Ich hab in meinem ersten Jahr bei Java Fleet diesen Unterschied nicht verstanden. Resultat? Eine Anwendung, die nach jeder kleinen Änderung neu deployed werden musste. Not fun. 😅

Lass uns das gemeinsam richtig lernen!


🟢 GRUNDLAGEN: Die zwei Arten von Includes

Das Problem: Code-Wiederverwendung in JSPs

Stell dir vor:

Du baust eine Webseite mit 20 Seiten. Alle haben denselben Header und Footer.

Naive Lösung (Kopieren & Einfügen):

<!-- page1.jsp -->
<!DOCTYPE html>
<html>
<head>
    <title>Page 1</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <h1>My Website</h1>
        <nav>
            <a href="home">Home</a>
            <a href="about">About</a>
        </nav>
    </header>
    
    <main>
        <!-- Page 1 Content -->
    </main>
    
    <footer>
        <p>&copy; 2025 My Company</p>
    </footer>
</body>
</html>

Problem:

  • Header und Footer sind auf ALLEN 20 Seiten dupliziert
  • Änderung am Header? → 20 Dateien ändern!
  • Fehleranfällig
  • Unmöglich zu warten

Lösung: Includes!

Extrahiere wiederverwendbare Teile in separate Dateien:

/includes/
├── header.jsp
└── footer.jsp

Und binde sie ein:

<!-- page1.jsp -->
<!-- Include Header -->
<header-content-here>

<main>
    <!-- Page 1 Content -->
</main>

<!-- Include Footer -->
<footer-content-here>

Aber wie genau?

Hier kommen die zwei Include-Mechanismen ins Spiel!


Include-Mechanismus #1: Include-Direktive <%@ include %>

Syntax:

<%@ include file="path/to/file.jsp" %>

Beispiel:

<!DOCTYPE html>
<html>
<head>
    <title>My Page</title>
</head>
<body>
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main>
        <h1>Welcome!</h1>
        <p>This is my page content.</p>
    </main>
    
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>

Was passiert?

  1. Translation-Zeit (Compile-Zeit)
  2. JSP-Container liest page.jsp
  3. Findet <%@ include file="header.jsp" %>
  4. Kopiert den gesamten Inhalt von header.jsp in page.jsp
  5. Kompiliert ALLES zusammen als EINE Servlet-Klasse

Visuell:

BEVOR Kompilierung:
┌─────────────────┐
│   page.jsp      │
│ <%@ include ... │  ──┐
│   <main>...     │    │
│ <%@ include ... │  ──┤
└─────────────────┘    │
                       │
┌─────────────────┐    │
│   header.jsp    │ <──┘
│ <header>...     │    
└─────────────────┘    
                       
┌─────────────────┐    
│   footer.jsp    │ <──┘
│ <footer>...     │
└─────────────────┘

NACH Kompilierung:
┌──────────────────────────┐
│  PageServlet.class       │
│  (ALLES zusammen!)       │
│                          │
│  - Header-Code           │
│  - Main-Content          │
│  - Footer-Code           │
└──────────────────────────┘

Wichtige Eigenschaften:

Compile-Time – Vor der Kompilierung ✅ Statisch – Inhalt wird direkt eingefügt (wie Copy/Paste) ✅ Schnell – Nur eine Servlet-Klasse ✅ File-Attributfile="..."

⚠️ Achtung:

  • Änderungen an header.jsppage.jsp muss neu kompiliert werden!
  • Kein dynamisches Einbinden möglich
  • Keine Parameter übergeben

Include-Mechanismus #2: Include-Action <jsp:include>

Syntax:

<jsp:include page="path/to/file.jsp" />

Beispiel:

<!DOCTYPE html>
<html>
<head>
    <title>My Page</title>
</head>
<body>
    <jsp:include page="/WEB-INF/includes/header.jsp" />
    
    <main>
        <h1>Welcome!</h1>
        <p>This is my page content.</p>
    </main>
    
    <jsp:include page="/WEB-INF/includes/footer.jsp" />
</body>
</html>

Was passiert?

  1. Runtime (Request-Zeit)
  2. Browser sendet Request an page.jsp
  3. Servlet führt aus
  4. Findet <jsp:include page="header.jsp" />
  5. Ruft header.jsp als separates Servlet auf
  6. Nimmt die Response von header.jsp und fügt sie in die eigene Response ein
  7. Macht weiter mit Main-Content
  8. Wiederholt für footer.jsp

Visuell:

Request kommt an:
┌────────────────────┐
│  Browser Request   │
└──────┬─────────────┘
       │
       ▼
┌────────────────────┐
│  PageServlet       │
│                    │
│  1. Generate HTML  │
│  2. ──> Call HeaderServlet  ──┐
│  3. Insert Response            │
│  4. Generate Content           │
│  5. ──> Call FooterServlet  ───┤
│  6. Insert Response            │
│  7. Send Complete Response     │
└────────────────────┘           │
                                 │
       ┌─────────────────────────┘
       │
       ▼
┌────────────────────┐
│  HeaderServlet     │ (Separate Klasse!)
│  <header>...       │
└────────────────────┘

┌────────────────────┐
│  FooterServlet     │ (Separate Klasse!)
│  <footer>...       │
└────────────────────┘

Wichtige Eigenschaften:

Runtime – Während Request-Ausführung ✅ Dynamisch – Kann zur Laufzeit entscheiden, was included wird ✅ Flexibel – Kann Parameter übergeben ✅ Page-Attributpage="..."Hot-Reload – Änderungen an header.jsp sofort sichtbar (kein Recompile!)

⚠️ Achtung:

  • Etwas langsamer (separater Servlet-Call)
  • Mehr Overhead

🟢 GRUNDLAGEN: Der große Vergleich

Side-by-Side Comparison

Feature<%@ include file="..." %><jsp:include page="..." />
ZeitpunktCompile-Time (Translation)Runtime (Request)
MechanismusCopy/Paste InhaltServlet-Call
Attribut-Namefile=""page=""
KompilierungAlles zusammen = 1 ServletSeparate Servlets
Geschwindigkeit⚡ Schneller⚡ Etwas langsamer
ÄnderungenRecompile nötig✅ Sofort sichtbar
Parameter❌ Nicht möglich✅ Möglich!
Dynamisch❌ Statisch✅ Dynamisch
Use-CaseHeader/Footer (statisch)User-Info, Widgets (dynamisch)

Praktisches Beispiel: Beide in Action

Projekt-Struktur:

MyApp/
├── src/main/webapp/
│   ├── index.jsp
│   └── WEB-INF/
│       ├── includes/
│       │   ├── header.jsp      (statisch - Include-Direktive)
│       │   ├── footer.jsp      (statisch - Include-Direktive)
│       │   └── userInfo.jsp    (dynamisch - Include-Action)
│       └── web.xml

header.jsp (Statisch – ändert sich selten):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<header style="background-color: #333; color: white; padding: 20px;">
    <h1>🚀 Java Fleet Systems</h1>
    <nav>
        <a href="${pageContext.request.contextPath}/">Home</a> |
        <a href="${pageContext.request.contextPath}/about">About</a> |
        <a href="${pageContext.request.contextPath}/contact">Contact</a>
    </nav>
</header>

footer.jsp (Statisch – ändert sich selten):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<footer style="background-color: #333; color: white; padding: 20px; text-align: center; margin-top: 40px;">
    <p>&copy; 2025 Java Fleet Systems Consulting</p>
    <p>Built with Jakarta EE 10 | <a href="mailto:support@java-developer.online" style="color: #4CAF50;">Contact Support</a></p>
</footer>

userInfo.jsp (Dynamisch – braucht Parameter):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<div style="border: 2px solid #4CAF50; border-radius: 10px; padding: 15px; background-color: #f0f0f0; margin: 20px 0;">
    <h3>👤 User Info</h3>
    
    <c:choose>
        <c:when test="${not empty sessionScope.currentUser}">
            <p><strong>Welcome back, ${sessionScope.currentUser.username}!</strong></p>
            <p>Email: ${sessionScope.currentUser.email}</p>
            <p>Role: ${sessionScope.currentUser.role}</p>
            <p>Page Context: ${param.context}</p>
        </c:when>
        <c:otherwise>
            <p>You are not logged in.</p>
            <p><a href="${pageContext.request.contextPath}/login">Login</a></p>
        </c:otherwise>
    </c:choose>
</div>

index.jsp (Nutzt BEIDE Mechanismen):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Include Demo - Java Fleet</title>
</head>
<body>
    <!-- INCLUDE-DIREKTIVE: Statischer Header (Compile-Time) -->
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main style="padding: 20px; max-width: 1200px; margin: 0 auto;">
        <h2>Welcome to Java Fleet!</h2>
        <p>This page demonstrates the difference between Include-Directive and Include-Action.</p>
        
        <!-- INCLUDE-ACTION: Dynamische User-Info (Runtime) -->
        <jsp:include page="/WEB-INF/includes/userInfo.jsp">
            <jsp:param name="context" value="Homepage" />
        </jsp:include>
        
        <div style="margin-top: 30px;">
            <h3>About This Demo</h3>
            <p><strong>Header & Footer:</strong> Using <code>&lt;%@ include file="..." %&gt;</code> (Compile-Time)</p>
            <p><strong>User Info:</strong> Using <code>&lt;jsp:include page="..." /&gt;</code> (Runtime)</p>
        </div>
    </main>
    
    <!-- INCLUDE-DIREKTIVE: Statischer Footer (Compile-Time) -->
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>

Was passiert hier?

  1. Header & Footer:
    • Verwendet <%@ include file="..." %>
    • Wird zur Compile-Zeit eingefügt
    • Eine Servlet-Klasse
    • Schnell!
  2. User Info:
    • Verwendet <jsp:include page="..." />
    • Wird zur Runtime aufgerufen
    • Kann Parameter übergeben (context="Homepage")
    • Zeigt aktuelle User-Daten aus Session
    • Flexibel!

🟢 GRUNDLAGEN: Parameter übergeben mit Include-Action

Die Superkraft von <jsp:include>: Parameter!

Warum ist das wichtig?

Manchmal willst du Daten an die included Datei übergeben!

Syntax:

<jsp:include page="/path/to/file.jsp">
    <jsp:param name="paramName" value="paramValue" />
    <jsp:param name="anotherParam" value="${someValue}" />
</jsp:include>

Beispiel: Product-Card-Komponente

productCard.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<div class="product-card" style="border: 1px solid #ddd; border-radius: 10px; padding: 20px; margin: 10px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);">
    <h3>${param.productName}</h3>
    <p class="category" style="color: #666;">Category: ${param.category}</p>
    <p class="price" style="font-size: 24px; color: #4CAF50; font-weight: bold;">
        <fmt:formatNumber value="${param.price}" type="currency" currencySymbol="€"/>
    </p>
    <p class="description">${param.description}</p>
    <button style="background-color: #4CAF50; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer;">
        Add to Cart
    </button>
</div>

products.jsp: (Nutzt die Komponente mehrfach)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>Products - Java Fleet Shop</title>
</head>
<body>
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main style="padding: 20px;">
        <h2>Our Products</h2>
        
        <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;">
            <!-- Product 1 -->
            <jsp:include page="/WEB-INF/components/productCard.jsp">
                <jsp:param name="productName" value="Laptop Dell XPS 15" />
                <jsp:param name="category" value="Electronics" />
                <jsp:param name="price" value="1299.99" />
                <jsp:param name="description" value="High-Performance Laptop" />
            </jsp:include>
            
            <!-- Product 2 -->
            <jsp:include page="/WEB-INF/components/productCard.jsp">
                <jsp:param name="productName" value="iPhone 15 Pro" />
                <jsp:param name="category" value="Electronics" />
                <jsp:param name="price" value="1199.99" />
                <jsp:param name="description" value="Apple Smartphone with A17 Chip" />
            </jsp:include>
            
            <!-- Product 3 -->
            <jsp:include page="/WEB-INF/components/productCard.jsp">
                <jsp:param name="productName" value="Sony WH-1000XM5" />
                <jsp:param name="category" value="Audio" />
                <jsp:param name="price" value="379.99" />
                <jsp:param name="description" value="Premium Noise-Cancelling Headphones" />
            </jsp:include>
        </div>
    </main>
    
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>

Was passiert?

  1. products.jsp ruft productCard.jsp 3x auf
  2. Jedes Mal mit unterschiedlichen Parametern
  3. productCard.jsp greift auf Parameter zu via ${param.productName}, etc.
  4. Resultat: 3 Produkt-Karten mit unterschiedlichen Daten!

Das ist die Power von <jsp:include>!


Include-Action mit dynamischem Page-Wert

Das Killer-Feature:

Du kannst zur Runtime entscheiden, welche Datei included wird!

Beispiel: Conditional Include

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
    <title>Dashboard</title>
</head>
<body>
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main>
        <h2>Dashboard</h2>
        
        <!-- Dynamisch entscheiden, welches Widget angezeigt wird -->
        <c:choose>
            <c:when test="${sessionScope.currentUser.role == 'Admin'}">
                <jsp:include page="/WEB-INF/widgets/adminWidget.jsp" />
            </c:when>
            <c:when test="${sessionScope.currentUser.role == 'Developer'}">
                <jsp:include page="/WEB-INF/widgets/developerWidget.jsp" />
            </c:when>
            <c:otherwise>
                <jsp:include page="/WEB-INF/widgets/userWidget.jsp" />
            </c:otherwise>
        </c:choose>
    </main>
    
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>

Oder mit EL-Expression:

<!-- Include basiert auf Request-Parameter -->
<jsp:include page="/WEB-INF/widgets/${param.widgetType}.jsp" />

<!-- URL: dashboard?widgetType=statistics → /WEB-INF/widgets/statistics.jsp -->

Das geht mit <%@ include file="..." %> NICHT!


🟡 PROFESSIONALS: Performance & Best Practices

Performance-Analyse: Wann ist was schneller?

Include-Direktive <%@ include file="..." %>:

Vorteile:

  • Nur eine Servlet-Klasse
  • Kein Overhead zur Runtime
  • Schneller bei vielen kleinen Includes

⚠️ Nachteile:

  • Recompile nötig bei Änderungen
  • GrößereServlet-Klasse
  • Längere Compile-Zeit

Use-Case:

  • Header/Footer (ändert sich selten)
  • Statische Includes (CSS-Variablen, Config)
  • Wenn Performance kritisch ist

Include-Action <jsp:include page="..." />:

Vorteile:

  • Hot-Reload – Änderungen sofort sichtbar
  • Flexibel – Parameter übergeben
  • Dynamisch – Runtime-Entscheidung

⚠️ Nachteile:

  • Separater Servlet-Call – leichter Overhead
  • Etwas langsamer (meist vernachlässigbar)

Use-Case:

  • User-spezifische Komponenten
  • Dynamische Widgets
  • Wenn Flexibilität wichtiger als Millisekunden ist

Benchmark (vereinfacht):

10.000 Requests, Header + Footer + Content:

Include-Direktive:
- 10ms avg per request
- Gesamt: 100 Sekunden

Include-Action:
- 12ms avg per request
- Gesamt: 120 Sekunden

Unterschied: 20 Sekunden (20%)

Real Talk:

Für 99% aller Anwendungen ist dieser Unterschied irrelevant!

Nutze <jsp:include> für Flexibilität, außer du hast echte Performance-Probleme.


Best Practice #1: Hybride Strategie

Die beste Lösung: Kombiniere beide!

Statisch (selten geändert):
✅ <%@ include file="..." %>
- header.jsp
- footer.jsp
- analytics.jsp
- meta-tags.jsp

Dynamisch (häufig geändert, Parameter):
✅ <jsp:include page="..." />
- userInfo.jsp
- notifications.jsp
- widgets/*.jsp
- productCard.jsp

Beispiel:

<!DOCTYPE html>
<html>
<head>
    <%@ include file="/WEB-INF/includes/meta-tags.jsp" %>
    <title>My Page</title>
</head>
<body>
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main>
        <jsp:include page="/WEB-INF/components/userInfo.jsp" />
        <jsp:include page="/WEB-INF/components/notifications.jsp" />
        
        <!-- Main Content -->
    </main>
    
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
    <%@ include file="/WEB-INF/includes/analytics.jsp" %>
</body>
</html>

Best Practice #2: Verzeichnis-Struktur

Organisiere deine Includes sinnvoll:

/src/main/webapp/
├── WEB-INF/
│   ├── includes/           (Statische Includes mit <%@ include %>)
│   │   ├── header.jsp
│   │   ├── footer.jsp
│   │   ├── meta-tags.jsp
│   │   └── analytics.jsp
│   │
│   ├── components/         (Dynamische Komponenten mit <jsp:include>)
│   │   ├── userInfo.jsp
│   │   ├── notifications.jsp
│   │   ├── productCard.jsp
│   │   └── sidebar.jsp
│   │
│   └── widgets/            (Dynamische Widgets mit <jsp:include>)
│       ├── adminWidget.jsp
│       ├── developerWidget.jsp
│       └── userWidget.jsp

Naming-Convention:

/includes/      → <%@ include file="..." %>
/components/    → <jsp:include page="..." />
/widgets/       → <jsp:include page="..." />

Best Practice #3: Parameter-Handling

Saubere Parameter-Übergabe:

<!-- ✅ GUT: Explizite Parameter -->
<jsp:include page="/WEB-INF/components/userInfo.jsp">
    <jsp:param name="userId" value="${sessionScope.currentUser.id}" />
    <jsp:param name="showAvatar" value="true" />
    <jsp:param name="context" value="Dashboard" />
</jsp:include>
<!-- ❌ SCHLECHT: Verlässt sich auf Session -->
<jsp:include page="/WEB-INF/components/userInfo.jsp" />
<!-- userInfo.jsp muss selbst in Session suchen -->

Warum ist explizit besser?

  1. Klar – Man sieht sofort, welche Daten übergeben werden
  2. Testbar – Komponente ist unabhängig
  3. Wiederverwendbar – Funktioniert in verschiedenen Kontexten
  4. Dokumentiert – Parameter sind self-explanatory

Best Practice #4: Error Handling

Included-Dateien sollten robust sein:

<!-- productCard.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!-- Validierung -->
<c:choose>
    <c:when test="${empty param.productName or empty param.price}">
        <div class="error" style="border: 2px solid red; padding: 10px; color: red;">
            <strong>Error:</strong> Missing required parameters (productName, price)
        </div>
    </c:when>
    <c:otherwise>
        <!-- Normal rendering -->
        <div class="product-card">
            <h3>${param.productName}</h3>
            <p>${param.price}</p>
        </div>
    </c:otherwise>
</c:choose>

Default-Werte:

<!-- Mit Default-Werten -->
<c:set var="showAvatar" value="${not empty param.showAvatar ? param.showAvatar : 'false'}" />
<c:set var="avatarSize" value="${not empty param.avatarSize ? param.avatarSize : '50'}" />

<c:if test="${showAvatar == 'true'}">
    <img src="${user.avatarUrl}" width="${avatarSize}" height="${avatarSize}" />
</c:if>

Best Practice #5: Caching-Überlegungen

Problem mit Include-Direktive:

header.jsp geändert
→ ALLE JSPs, die header.jsp includen, müssen neu kompiliert werden!

In großen Projekten:

  • 100 JSPs includen header.jsp
  • Header ändern → 100 JSPs recompilen
  • Deployment dauert Ewigkeiten

Lösung 1: Include-Action verwenden

<!-- ✅ Besser für häufige Änderungen -->
<jsp:include page="/WEB-INF/includes/header.jsp" />

Lösung 2: Precompile-JSPs

<!-- In pom.xml -->
<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-jspc-maven-plugin</artifactId>
    <version>11.0.13</version>
    <executions>
        <execution>
            <goals>
                <goal>jspc</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Best Practice #6: Scope Awareness

Important:

Included-Dateien teilen denselben Scope wie die Haupt-JSP!

<!-- main.jsp -->
<%
    String message = "Hello from Main";
    request.setAttribute("message", message);
%>

<jsp:include page="/WEB-INF/includes/display.jsp" />
<!-- display.jsp -->
<p>Message: ${requestScope.message}</p>
<!-- Zeigt: "Hello from Main" -->

Das gilt für:

  • Request-Scope
  • Session-Scope
  • Application-Scope
  • Page-Scope (nur bei Include-Direktive!)

Vorsicht bei Namenskonflikten:

<!-- main.jsp -->
<c:set var="title" value="Main Page" />

<jsp:include page="/WEB-INF/includes/sidebar.jsp" />
<!-- sidebar.jsp -->
<c:set var="title" value="Sidebar" />  <!-- Überschreibt "Main Page"! -->

Lösung: Namespacing

<!-- sidebar.jsp -->
<c:set var="sidebarTitle" value="Sidebar" />

🟡 PROFESSIONALS: Fortgeschrittene Techniken

Technik #1: Include-Chain

Du kannst Includes schachteln:

main.jsp
  ├── header.jsp
  │     └── navigation.jsp
  ├── content.jsp
  │     ├── userInfo.jsp
  │     └── notifications.jsp
  └── footer.jsp
        └── socialLinks.jsp

Beispiel:

<!-- header.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<header>
    <h1>My Website</h1>
    
    <!-- Nested Include -->
    <jsp:include page="/WEB-INF/includes/navigation.jsp" />
</header>

Vorsicht:

  • Zu viele verschachtelte Includes → Performance-Problem
  • Schwer zu debuggen
  • Empfehlung: Max. 2-3 Ebenen

Technik #2: Conditional Include mit Servlet

Servlet entscheidet, welche JSP included wird:

WidgetServlet.java:

package com.javafleet.controller;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;

@WebServlet("/widget")
public class WidgetServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) 
                        throws ServletException, IOException {
        
        // Entscheide basierend auf User-Role
        HttpSession session = request.getSession();
        String role = (String) session.getAttribute("userRole");
        
        String widgetPath;
        if ("Admin".equals(role)) {
            widgetPath = "/WEB-INF/widgets/adminWidget.jsp";
        } else if ("Developer".equals(role)) {
            widgetPath = "/WEB-INF/widgets/developerWidget.jsp";
        } else {
            widgetPath = "/WEB-INF/widgets/userWidget.jsp";
        }
        
        // Forward zu entsprechendem Widget
        request.getRequestDispatcher(widgetPath).forward(request, response);
    }
}

dashboard.jsp:

<!DOCTYPE html>
<html>
<body>
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main>
        <h2>Dashboard</h2>
        
        <!-- Servlet-basiertes Include -->
        <jsp:include page="/widget" />
    </main>
    
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>

Technik #3: Fragment-Include mit Anchors

Du kannst nur einen Teil einer Datei includen (in manchen Containern):

<!-- Include nur den Teil nach #content -->
<jsp:include page="/WEB-INF/includes/fullPage.jsp#content" />

fullPage.jsp:

<!DOCTYPE html>
<html>
<body>
    <header>Header Content</header>
    
    <!-- Anchor -->
    <a name="content"></a>
    
    <main>
        This part gets included!
    </main>
    
    <footer>Footer Content</footer>
</body>
</html>

Achtung:

  • Nicht alle Container unterstützen das!
  • Besser: Separate Dateien verwenden

Technik #4: Buffer-Flushing

Problem:

Bei vielen Includes kann der Output-Buffer volllaufen.

Lösung:

<%@ page buffer="8kb" autoFlush="true" %>

Oder manuell:

<jsp:include page="/WEB-INF/includes/header.jsp" flush="true" />

Vorsicht:

  • Nach flush="true" kannst du keine Headers mehr setzen!
  • Kann zu Performance-Problemen führen

Technik #5: Include mit Request-Wrapping

Erweiterte Technik: Eigener Request-Wrapper

package com.javafleet.wrapper;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.util.HashMap;
import java.util.Map;

public class ParameterRequestWrapper extends HttpServletRequestWrapper {
    
    private Map<String, String[]> customParams = new HashMap<>();
    
    public ParameterRequestWrapper(HttpServletRequest request) {
        super(request);
    }
    
    public void addParameter(String name, String value) {
        customParams.put(name, new String[]{value});
    }
    
    @Override
    public String getParameter(String name) {
        if (customParams.containsKey(name)) {
            return customParams.get(name)[0];
        }
        return super.getParameter(name);
    }
}

Nutzen im Servlet:

ParameterRequestWrapper wrapper = new ParameterRequestWrapper(request);
wrapper.addParameter("customParam", "value");
request.getRequestDispatcher("/include.jsp").include(wrapper, response);

🔵 BONUS: Real-World Patterns

Pattern #1: Template Method Pattern

Idee:

Ein Template definiert die Struktur, konkrete Seiten füllen die Inhalte.

template.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>${param.pageTitle}</title>
    <%@ include file="/WEB-INF/includes/meta-tags.jsp" %>
</head>
<body>
    <%@ include file="/WEB-INF/includes/header.jsp" %>
    
    <main>
        <!-- Content-Bereich: Wird von konkreter Seite gefüllt -->
        <jsp:include page="${param.contentPage}" />
    </main>
    
    <%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>

products.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:include page="/WEB-INF/templates/template.jsp">
    <jsp:param name="pageTitle" value="Products" />
    <jsp:param name="contentPage" value="/WEB-INF/content/productsContent.jsp" />
</jsp:include>

productsContent.jsp:

<h2>Our Products</h2>
<p>Welcome to our product page...</p>
<!-- Product list -->

Vorteile:

  • DRY (Don’t Repeat Yourself)
  • Einheitliches Layout
  • Leicht zu warten

Pattern #2: Component-Based Architecture

Idee:

Baue wiederverwendbare Komponenten wie in React/Vue!

/components/
├── Button.jsp
├── Card.jsp
├── Modal.jsp
├── Alert.jsp
└── ProductCard.jsp

Button.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<c:set var="btnType" value="${not empty param.type ? param.type : 'primary'}" />
<c:set var="btnSize" value="${not empty param.size ? param.size : 'medium'}" />

<c:choose>
    <c:when test="${btnType == 'primary'}">
        <c:set var="bgColor" value="#4CAF50" />
    </c:when>
    <c:when test="${btnType == 'danger'}">
        <c:set var="bgColor" value="#f44336" />
    </c:when>
    <c:otherwise>
        <c:set var="bgColor" value="#2196F3" />
    </c:otherwise>
</c:choose>

<button style="background-color: ${bgColor}; color: white; border: none; padding: ${btnSize == 'large' ? '15px 30px' : '10px 20px'}; border-radius: 5px; cursor: pointer; font-size: ${btnSize == 'large' ? '18px' : '16px'};">
    ${param.label}
</button>

Nutzung:

<jsp:include page="/WEB-INF/components/Button.jsp">
    <jsp:param name="label" value="Submit" />
    <jsp:param name="type" value="primary" />
    <jsp:param name="size" value="large" />
</jsp:include>

<jsp:include page="/WEB-INF/components/Button.jsp">
    <jsp:param name="label" value="Cancel" />
    <jsp:param name="type" value="danger" />
</jsp:include>

Pattern #3: Layout-Composition

Idee:

Verschiedene Layouts für verschiedene Seiten.

/layouts/
├── main.jsp          (Header + Content + Footer)
├── sidebar.jsp       (Header + Sidebar + Content + Footer)
├── fullwidth.jsp     (Full-Width ohne Sidebar)
└── admin.jsp         (Admin-Layout mit Dashboard)

Servlet wählt Layout:

@WebServlet("/page")
public class PageServlet extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) 
                        throws ServletException, IOException {
        
        String layout = request.getParameter("layout");
        
        if (layout == null) {
            layout = "main";
        }
        
        request.setAttribute("contentPage", "/WEB-INF/content/myContent.jsp");
        
        request.getRequestDispatcher("/WEB-INF/layouts/" + layout + ".jsp")
               .forward(request, response);
    }
}

💬 Real Talk: Mittagspause-Gespräch

Java Fleet Küche, 12:45 Uhr. Kat holt sich einen Kaffee, Nova sitzt mit ihrem Laptop am Tisch, Kofi macht sich ein Sandwich.


Nova: „Kat, du hast doch letzte Woche die Legacy-Anwendung refactored – wie viele Includes hattest du da?“

Kat: „Oh Mann, don’t even get me started. Über 50. Und fast ALLE mit <%@ include file="..." %>.“

Nova: „Was war das Problem?“

Kat: „Jede kleine Änderung am Header → komplettes Re-Deployment der ganzen App. 15 Minuten Build-Zeit. Every. Single. Time.“

Kofi (zwischendurch): „Das klingt nach einem Albtraum für Entwicklung.“

Kat: „War es auch! Ich hab dann alles auf <jsp:include> umgestellt – wenigstens für die Teile, die sich häufiger ändern.“

Nova: „Und? Besser geworden?“

Kat: „Huge improvement! Änderungen am Header? Hot-Reload, fertig. Keine 15 Minuten mehr warten.“

Nova: „Aber ich dachte, <%@ include %> ist schneller?“

Kat (nimmt einen Schluck Kaffee): „Technically ja. In der Praxis? Egal. Der Performance-Unterschied ist so minimal – aber die Developer Experience? Day and night.“

Kofi: „Real talk: Franz-Martin hat mir mal gesagt, die alten Java-Devs haben ALLES mit Include-Direktive gemacht. Das war damals Best Practice.“

Nova: „Warum?“

Kofi: „Server waren langsamer damals. Jeder Millisekunde hat gezählt. Aber heute? Mit modernen Servern? Honestly, du merkst keinen Unterschied.“

Kat: „Genau! Und wenn du wirklich Performance-Probleme hast, liegt’s nicht an den Includes. Dann hast du größere Probleme.“

Nova (nachdenklich): „Also sollte ich standardmäßig <jsp:include> verwenden?“

Kat: „Für alles, was sich öfter ändert oder wo du Parameter brauchst – yes! Für total statische Sachen wie Analytics-Snippets? Dann kannst du <%@ include %> nehmen.“

Kofi: „Hybrid Approach. Best of both worlds.“

Nova (grinst): „Lowkey macht das Sinn. Thanks!“


✅ Checkpoint: Hast du es verstanden?

Bevor du weitermachst, teste dich selbst:

Quiz:

Frage 1: Was ist der Hauptunterschied zwischen <%@ include file="..." %> und <jsp:include page="..." />?

Frage 2: Wann verwendet man <%@ include file="..." %>? Nenne 3 Use-Cases.

Frage 3: Wie übergibst du Parameter an eine Include-Action? Zeige Code-Beispiel.

Frage 4: Was passiert, wenn du eine mit <%@ include file="..." %> eingebundene Datei änderst?

Frage 5: Welche Include-Methode ist in 99% der Fälle die bessere Wahl für moderne Anwendungen und warum?


Mini-Challenge:

Aufgabe: Erstelle eine Component-Library mit wiederverwendbaren JSP-Komponenten.

Anforderungen:

  1. Erstelle ein /WEB-INF/components/ Verzeichnis
  2. Erstelle folgende Komponenten mit <jsp:include>:
    • Alert.jsp (mit Parameters: type, message)
    • Button.jsp (mit Parameters: label, type, size)
    • Card.jsp (mit Parameters: title, content)
  3. Erstelle ein /WEB-INF/includes/ Verzeichnis
  4. Erstelle folgende statische Includes mit <%@ include %>:
    • header.jsp
    • footer.jsp
    • meta-tags.jsp
  5. Erstelle eine demo.jsp, die alle Komponenten verwendet
  6. Teste Hot-Reload: Ändere Alert.jsp → sollte sofort sichtbar sein
  7. Teste Compile-Time: Ändere header.jsp → Neustart nötig?

Bonus:

  • Erstelle ein Template-Layout-System
  • Implementiere Default-Werte für alle Parameter
  • Füge Fehlerbehandlung hinzu (fehlende Parameter)

❓ Häufig gestellte Fragen

Frage 1: Kann ich mit <%@ include file="..." %> auch Parameter übergeben?

Nein! Das ist ein Compile-Time Include – es gibt keine Runtime-Parameter.

<!-- ❌ Geht NICHT: -->
<%@ include file="/header.jsp?title=MyPage" %>

Lösung:

Setze Variablen VOR dem Include:

<!-- ✅ Funktioniert: -->
<%
    String pageTitle = "My Page";
%>
<%@ include file="/header.jsp" %>

In header.jsp:

<title><%= pageTitle %></title>

Aber: Besser <jsp:include> mit Parametern verwenden!


Frage 2: Was passiert, wenn die included Datei einen Fehler hat?

Mit <%@ include file="..." %>:

  • Fehler zur Compile-Zeit
  • Alle JSPs, die diese Datei includen, können nicht kompiliert werden
  • Komplettes Re-Deployment nötig

Mit <jsp:include page="..." />:

  • Fehler zur Runtime
  • Nur die aufgerufene Seite zeigt Fehler
  • Andere Seiten funktionieren weiter
  • Exception wird in Response geschrieben (oder Error-Page)

Real-World:

<jsp:include> ist fehlertoleranter!


Frage 3: Kann ich Includes verschachteln? Wie tief?

Ja, du kannst Includes schachteln!

main.jsp
  → includes header.jsp
    → includes navigation.jsp
      → includes menuItems.jsp

Aber:

  • Performance-Impact bei zu vielen Ebenen
  • Schwer zu debuggen
  • Empfehlung: Max. 2-3 Ebenen

Best Practice:

Flache Hierarchie ist besser:

main.jsp
  → includes header.jsp
  → includes navigation.jsp
  → includes sidebar.jsp
  → includes footer.jsp

Frage 4: Funktioniert <jsp:include> mit Dateien außerhalb von WEB-INF?

Ja, aber es sollte vermieden werden!

<!-- ❌ SCHLECHT: -->
<jsp:include page="/publicFolder/widget.jsp" />

Warum schlecht?

  • Dateien außerhalb /WEB-INF/ sind direkt erreichbar via URL
  • Security-Risiko
  • Nutzer könnten Widget direkt aufrufen

Best Practice:

<!-- ✅ GUT: -->
<jsp:include page="/WEB-INF/components/widget.jsp" />

Dateien in /WEB-INF/ sind geschützt – nur via Include/Forward erreichbar!


Frage 5: Kann ich mit <jsp:include> Daten zurückbekommen?

Nicht direkt! <jsp:include> fügt nur die Response ein.

Aber:

Du kannst Request-Attribute setzen:

included.jsp:

<%
    request.setAttribute("result", "Success!");
%>
<p>This is included content.</p>

main.jsp:

<jsp:include page="/included.jsp" />

<!-- Danach: -->
<p>Result from include: ${requestScope.result}</p>

Alternative:

Custom Tags (JSTL – Tag 8!) sind besser für komplexe Logik!


Frage 6: Gibt es Performance-Probleme bei vielen <jsp:include> Calls?

Kurze Antwort: Normalerweise nein.

Lange Antwort:

Jeder <jsp:include> Call:

  • Ruft separates Servlet auf
  • Leichter Overhead (~1-2ms)

Bei 100+ Includes auf einer Seite:

  • Kann spürbar werden
  • Aber: Wer macht das? 🤔

Real-World:

Typische Seite: 5-10 Includes → kein Problem!

Wenn du wirklich Performance brauchst:

  • Nutze <%@ include file="..." %> für statische Teile
  • Caching (Tag Library mit Cache-Support)
  • Fragment-Caching (Varnish, Nginx)

Frage 7: Bernd meinte mal, „Includes sind der Anfang von Spaghetti-Code“. Hat er recht?

Lowkey ja – aber nur, wenn man’s falsch macht!

❌ Spaghetti-Code mit Includes:

main.jsp
  → includes header.jsp
    → includes topNav.jsp
      → includes userMenu.jsp
        → includes profileLink.jsp (WTF?)

5 Ebenen tief? That’s a mess.

✅ Sauberer Code mit Includes:

main.jsp
  → header.jsp (statisch)
  → userInfo.jsp (dynamisch, mit Parametern)
  → content.jsp
  → footer.jsp (statisch)

Flach, klar, wartbar!

Bernds Weisheit:

„Includes sind wie Salz – ein bisschen ist gut, zu viel versaut das Gericht.“

Real talk: Wenn deine Include-Struktur aussieht wie ein Inception-Movie, hast du ein Problem. Keep it simple!


📚 Quiz-Lösungen

Hier sind die Antworten zum Quiz von oben:


Frage 1: Was ist der Hauptunterschied zwischen <%@ include file="..." %> und <jsp:include page="..." />?

Antwort:

Hauptunterschied: WANN das Include passiert!

<%@ include file="..." %>:

  • Compile-Time (Translation-Phase)
  • Datei-Inhalt wird direkt eingefügt (Copy/Paste)
  • Beide Dateien werden zu EINER Servlet-Klasse kompiliert
  • Statisch
  • Schneller
  • Keine Parameter möglich

<jsp:include page="..." />:

  • Runtime (Request-Phase)
  • Separates Servlet wird aufgerufen
  • Response wird eingefügt
  • Dynamisch
  • Flexibel
  • Parameter möglich

Code-Beispiel:

<!-- Compile-Time -->
<%@ include file="/WEB-INF/includes/header.jsp" %>

<!-- Runtime -->
<jsp:include page="/WEB-INF/components/userInfo.jsp">
    <jsp:param name="userId" value="${sessionScope.currentUser.id}" />
</jsp:include>

Frage 2: Wann verwendet man <%@ include file="..." %>? Nenne 3 Use-Cases.

Antwort:

Use-Case 1: Statischer Header/Footer

<%@ include file="/WEB-INF/includes/header.jsp" %>
  • Ändert sich selten
  • Auf jeder Seite gleich
  • Performance-optimal

Use-Case 2: Meta-Tags & Analytics

<%@ include file="/WEB-INF/includes/meta-tags.jsp" %>
<%@ include file="/WEB-INF/includes/analytics.jsp" %>
  • Statische Snippets
  • Keine Parameter nötig
  • Compile-Time ist OK

Use-Case 3: Globale Konstanten/Konfiguration

<%@ include file="/WEB-INF/includes/config.jsp" %>

config.jsp:

<%
    final String APP_VERSION = "1.0.0";
    final String SUPPORT_EMAIL = "support@java-developer.online";
%>
  • Wird in jeder JSP gebraucht
  • Ändert sich sehr selten
  • Compile-Time Optimierung sinnvoll

Frage 3: Wie übergibst du Parameter an eine Include-Action? Zeige Code-Beispiel.

Antwort:

Syntax:

<jsp:include page="/path/to/file.jsp">
    <jsp:param name="parameterName" value="parameterValue" />
    <jsp:param name="anotherParam" value="${someExpression}" />
</jsp:include>

Vollständiges Beispiel:

main.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<body>
    <h1>Welcome</h1>
    
    <!-- Include mit Parametern -->
    <jsp:include page="/WEB-INF/components/userCard.jsp">
        <jsp:param name="username" value="${sessionScope.currentUser.username}" />
        <jsp:param name="email" value="${sessionScope.currentUser.email}" />
        <jsp:param name="showAvatar" value="true" />
        <jsp:param name="avatarSize" value="100" />
    </jsp:include>
</body>
</html>

userCard.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<div class="user-card">
    <h3>User Profile</h3>
    <p><strong>Username:</strong> ${param.username}</p>
    <p><strong>Email:</strong> ${param.email}</p>
    
    <c:if test="${param.showAvatar == 'true'}">
        <img src="/avatars/${param.username}.jpg" 
             width="${param.avatarSize}" 
             height="${param.avatarSize}" 
             alt="Avatar" />
    </c:if>
</div>

Zugriff auf Parameter in included JSP:

  • ${param.username}
  • ${param.email}
  • ${param.showAvatar}
  • etc.

Frage 4: Was passiert, wenn du eine mit <%@ include file="..." %> eingebundene Datei änderst?

Antwort:

Kurz: Die Haupt-JSP muss neu kompiliert werden!

Im Detail:

  1. Du änderst header.jsp
  2. header.jsp ist mit <%@ include file="header.jsp" %> in 20 JSPs eingebunden
  3. ALLE 20 JSPs müssen neu kompiliert werden!

Warum?

  • <%@ include file="..." %> ist Compile-Time
  • header.jsp Inhalt wird direkt in die JSP eingefügt
  • Servlet-Klasse enthält header.jsp Code
  • Änderung → neue Servlet-Klasse nötig

In der Praxis:

header.jsp ändern
→ Save
→ Application Server merkt Änderung
→ Alle JSPs mit <%@ include file="header.jsp" %> werden recompiled
→ Bei vielen Dateien: Dauert lange!
→ Production-Deployment: Ganzes WAR neu deployen

Mit <jsp:include page="..." /> wäre das nicht passiert:

header.jsp ändern
→ Save
→ Bei nächstem Request: Sofort sichtbar!
→ Kein Recompile, kein Re-Deployment

Real-World Konsequenz:

Wenn du häufig am Header arbeitest → nutze <jsp:include>!


Frage 5: Welche Include-Methode ist in 99% der Fälle die bessere Wahl für moderne Anwendungen und warum?

Antwort:

<jsp:include page="..." /> ist in 99% der Fälle besser!

Warum?

1. Flexibilität:

  • Parameter übergeben ✅
  • Dynamische Page-Auswahl ✅
  • Runtime-Entscheidungen ✅

2. Developer Experience:

  • Hot-Reload ✅
  • Keine Recompilierung nötig ✅
  • Schnellere Entwicklung ✅

3. Wartbarkeit:

  • Änderungen sofort sichtbar ✅
  • Kein komplettes Re-Deployment ✅
  • Einfacher zu debuggen ✅

4. Moderne Best Practices:

  • Component-Based Architecture ✅
  • Separation of Concerns ✅
  • Testbarkeit ✅

5. Performance ist kein Problem:

  • Minimaler Overhead (1-2ms)
  • Moderne Server sind schnell genug
  • Spürbar nur bei 100+ Includes (unrealistisch)

Ausnahmen (1% wo <%@ include file="..." %> besser ist):

  1. Absolute Performance-Kritisch:
    • High-Traffic Site (1 Mio+ Requests/Tag)
    • Jede Millisekunde zählt
    • Profiling zeigt Include-Overhead
  2. Komplett Statisch:
    • Analytics-Snippet (ändert sich nie)
    • Copyright-Footer (update einmal pro Jahr)
    • Meta-Tags (fix)
  3. Legacy-Code:
    • Bestehendes Projekt mit <%@ include %>
    • Refactoring nicht gerechtfertigt

Empfehlung:

Default: <jsp:include page="..." />

Nur wenn du einen sehr guten Grund hast → <%@ include file="..." %>


🎉 Tag 7 geschafft!

Main Character Energy! Du rockst! ✨

Real talk: Includes sind ein mega wichtiges Thema. Viele Entwickler nutzen die falsche Methode, weil sie den Unterschied nicht verstehen.

Das hast du heute gelernt:

  • ✅ Include-Direktive <%@ include file="..." %> (Compile-Time)
  • ✅ Include-Action <jsp:include page="..." /> (Runtime)
  • ✅ Wann du welches Include verwendest
  • ✅ Parameter an Includes übergeben
  • ✅ Performance-Unterschiede verstehen
  • ✅ Best Practices für modulare JSPs
  • ✅ Fortgeschrittene Patterns (Template Method, Components)

Du kannst jetzt:

  • Den Unterschied zwischen beiden Includes erklären
  • Die richtige Methode für verschiedene Szenarien wählen
  • Wiederverwendbare Komponenten mit Parametern bauen
  • Saubere, wartbare JSP-Strukturen erstellen
  • Performance-Optimierungen begründen

Honestly? Das ist ein Game-Changer! Du verstehst jetzt, wie man modulare, wartbare Webanwendungen mit JSPs baut.

Und lowkey: In vielen Legacy-Projekten werden Includes falsch genutzt. Mit diesem Wissen kannst du echte Verbesserungen bringen! 💪


🔮 Wie geht’s weiter?

Morgen (Tag 8): JSTL – Java Standard Tag Libraries

Was dich erwartet:

  • JSTL Core Tags (<c:forEach>, <c:if>, <c:choose>)
  • Formatting Tags (<fmt:formatNumber>, <fmt:formatDate>)
  • URL & XML Tags
  • Custom Tags erstellen
  • JSTL ist der moderne Weg – kein Java-Code mehr in JSPs! 🔥

Brauchst du eine Pause?
Mach sie! Include-Konzepte brauchen Zeit zum Verinnerlichen.

Tipp für heute Abend:
Schau dir ein bestehendes Projekt an (Open Source auf GitHub) und analysiere, welche Include-Methode verwendet wird. Siehst du Verbesserungspotenzial?

Learning by analyzing! 🎨


📧 Troubleshooting

Problem: Include funktioniert nicht – 404 Not Found

Lösung 1: Prüfe Pfad

<!-- ❌ FALSCH: Kein führender Slash -->
<jsp:include page="WEB-INF/includes/header.jsp" />

<!-- ✅ RICHTIG: Mit führendem Slash -->
<jsp:include page="/WEB-INF/includes/header.jsp" />

Lösung 2: Prüfe, ob Datei existiert

/src/main/webapp/
└── WEB-INF/
    └── includes/
        └── header.jsp  ← Muss hier sein!

Problem: Parameter kommen nicht an in included JSP

Symptom:

${param.username}  <!-- Zeigt nichts an! -->

Lösung:

Prüfe Syntax:

<!-- ❌ FALSCH: Falsche Attribute -->
<jsp:include page="/header.jsp">
    <jsp:param key="username" val="${user.username}" />
</jsp:include>

<!-- ✅ RICHTIG: name & value -->
<jsp:include page="/header.jsp">
    <jsp:param name="username" value="${user.username}" />
</jsp:include>

Problem: Änderungen an included Datei nicht sichtbar

Symptom:

header.jsp geändert, aber im Browser alte Version sichtbar.

Ursachen & Lösungen:

1. Browser-Cache:

Strg + F5 (Windows)
Cmd + Shift + R (Mac)

2. Server-Cache:

  • Payara: Clean & Build
  • Tomcat: Restart Server

3. Falsche Include-Methode:

<!-- Falls du <%@ include file="..." %> nutzt: -->
<%@ include file="/header.jsp" %>
<!-- → Komplettes Re-Deployment nötig! -->

<!-- Lösung: Wechsel zu <jsp:include> -->
<jsp:include page="/header.jsp" />

Problem: java.lang.IllegalStateException: Response already committed

Ursache:

Du versuchst, Headers zu setzen oder zu redirecten NACH einem Include mit flush="true".

<jsp:include page="/header.jsp" flush="true" />
<%
    response.sendRedirect("/login");  // ❌ Geht nicht mehr!
%>

Lösung:

Entferne flush="true" oder setze Headers VOR dem Include.


Problem: Performance-Probleme mit vielen Includes

Symptom:

Seite lädt langsam, viele <jsp:include> Calls.

Analyse:

<!-- Zu viele Includes? -->
<jsp:include page="/component1.jsp" />
<jsp:include page="/component2.jsp" />
<!-- ... 50 weitere ... -->

Lösungen:

  1. Kombiniere Komponenten:
<!-- Statt 10 kleine Includes: -->
<jsp:include page="/components/dashboardBundle.jsp" />
  1. Nutze <%@ include file="..." %> für statische Teile:
<%@ include file="/includes/criticalPath.jsp" %>
  1. Implementiere Caching (fortgeschritten):
  • Fragment-Caching
  • Varnish/Nginx vor Application Server

Viel Erfolg beim Lernen! 🚀

Wenn du Fragen hast, schreib uns: elyndra.valen@java-developer.online


„Includes sind wie Legosteine – richtig zusammengesetzt bauen sie Meisterwerke!“ – Elyndra Valen

Autor

  • Elyndra Valen

    28 Jahre alt, wurde kürzlich zur Senior Entwicklerin befördert nach 4 Jahren intensiver Java-Entwicklung. Elyndra kennt die wichtigsten Frameworks und Patterns, beginnt aber gerade erst, die tieferen Zusammenhänge und Architektur-Entscheidungen zu verstehen. Sie ist die Brücke zwischen Junior- und Senior-Welt im Team.