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

🗺️ Deine Position im Kurs
| Tag | Thema | Status |
|---|---|---|
| 1 | Java EE Überblick & HTTP (Teil 1) | ✅ Abgeschlossen |
| 2 | HTTP-Protokoll Vertiefung & Zustandslosigkeit | ✅ Abgeschlossen |
| 3 | Servlets & Servlet API | ✅ Abgeschlossen |
| 4 | Deployment Descriptor & MVC vs Model 2 | ✅ Abgeschlossen |
| 5 | JSP & Expression Languages (Teil 1) | ✅ Abgeschlossen |
| 6 | Java Beans, Actions, Scopes & Direktiven | ✅ Abgeschlossen |
| → 7 | Include-Action vs Include-Direktive | 👉 DU BIST HIER! |
| 8 | JSTL – Java Standard Tag Libraries | 🔒 Noch nicht freigeschaltet |
| 9 | Java Web und Datenbanken – Datasource | 🔒 Noch nicht freigeschaltet |
| 10 | Connection 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>© 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?
- Translation-Zeit (Compile-Zeit)
- JSP-Container liest
page.jsp - Findet
<%@ include file="header.jsp" %> - Kopiert den gesamten Inhalt von
header.jspinpage.jsp - 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-Attribut – file="..."
⚠️ Achtung:
- Änderungen an
header.jsp→page.jspmuss 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?
- Runtime (Request-Zeit)
- Browser sendet Request an
page.jsp - Servlet führt aus
- Findet
<jsp:include page="header.jsp" /> - Ruft
header.jspals separates Servlet auf - Nimmt die Response von
header.jspund fügt sie in die eigene Response ein - Macht weiter mit Main-Content
- 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-Attribut – page="..." ✅ 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="..." /> |
|---|---|---|
| Zeitpunkt | Compile-Time (Translation) | Runtime (Request) |
| Mechanismus | Copy/Paste Inhalt | Servlet-Call |
| Attribut-Name | file="" | page="" |
| Kompilierung | Alles zusammen = 1 Servlet | Separate Servlets |
| Geschwindigkeit | ⚡ Schneller | ⚡ Etwas langsamer |
| Änderungen | Recompile nötig | ✅ Sofort sichtbar |
| Parameter | ❌ Nicht möglich | ✅ Möglich! |
| Dynamisch | ❌ Statisch | ✅ Dynamisch |
| Use-Case | Header/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>© 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><%@ include file="..." %></code> (Compile-Time)</p>
<p><strong>User Info:</strong> Using <code><jsp:include page="..." /></code> (Runtime)</p>
</div>
</main>
<!-- INCLUDE-DIREKTIVE: Statischer Footer (Compile-Time) -->
<%@ include file="/WEB-INF/includes/footer.jsp" %>
</body>
</html>
Was passiert hier?
- Header & Footer:
- Verwendet
<%@ include file="..." %> - Wird zur Compile-Zeit eingefügt
- Eine Servlet-Klasse
- Schnell!
- Verwendet
- User Info:
- Verwendet
<jsp:include page="..." /> - Wird zur Runtime aufgerufen
- Kann Parameter übergeben (
context="Homepage") - Zeigt aktuelle User-Daten aus Session
- Flexibel!
- Verwendet
🟢 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?
products.jspruftproductCard.jsp3x auf- Jedes Mal mit unterschiedlichen Parametern
productCard.jspgreift auf Parameter zu via${param.productName}, etc.- 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?
- Klar – Man sieht sofort, welche Daten übergeben werden
- Testbar – Komponente ist unabhängig
- Wiederverwendbar – Funktioniert in verschiedenen Kontexten
- 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:
- Erstelle ein
/WEB-INF/components/Verzeichnis - 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)
- Erstelle ein
/WEB-INF/includes/Verzeichnis - Erstelle folgende statische Includes mit
<%@ include %>:header.jspfooter.jspmeta-tags.jsp
- Erstelle eine
demo.jsp, die alle Komponenten verwendet - Teste Hot-Reload: Ändere
Alert.jsp→ sollte sofort sichtbar sein - 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:
- Du änderst
header.jsp header.jspist mit<%@ include file="header.jsp" %>in 20 JSPs eingebunden- ALLE 20 JSPs müssen neu kompiliert werden!
Warum?
<%@ include file="..." %>ist Compile-Timeheader.jspInhalt wird direkt in die JSP eingefügt- Servlet-Klasse enthält
header.jspCode - Ä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):
- Absolute Performance-Kritisch:
- High-Traffic Site (1 Mio+ Requests/Tag)
- Jede Millisekunde zählt
- Profiling zeigt Include-Overhead
- Komplett Statisch:
- Analytics-Snippet (ändert sich nie)
- Copyright-Footer (update einmal pro Jahr)
- Meta-Tags (fix)
- Legacy-Code:
- Bestehendes Projekt mit
<%@ include %> - Refactoring nicht gerechtfertigt
- Bestehendes Projekt mit
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:
- Kombiniere Komponenten:
<!-- Statt 10 kleine Includes: --> <jsp:include page="/components/dashboardBundle.jsp" />
- Nutze
<%@ include file="..." %>für statische Teile:
<%@ include file="/includes/criticalPath.jsp" %>
- 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

