Inhalt | 6 |
Vorwort | 14 |
Danksagungen | 16 |
Über dieses Buch | 20 |
Teil 1: Struts 2 – Ein brandneues Framework | 25 |
1 Struts 2 – Das moderne Framework für Webanwendungen | 27 |
1.1 Webanwendungen – Ein kurzer Überblick | 28 |
1.1.1 Das Internet zum Erstellen von Anwendungen einsetzen | 28 |
1.1.2 Die technologische Basis | 28 |
1.1.2.1 Hypertext Transfer Protocol (HTTP) | 29 |
1.1.2.2 Die Java-Servlet-API | 30 |
1.1.3 Inspektion des Arbeitsbereichs | 33 |
1.1.3.1 Bindung von Anfrageparametern und Datenvalidierung | 33 |
1.1.3.2 Aufrufe der Businesslogik und der Datenschicht | 34 |
1.1.3.3 Rendern der Darstellung und Internationalisierung | 34 |
1.2 Frameworks für Webanwendungen | 35 |
1.2.1 Was ist ein Framework? | 35 |
1.2.1.1 Ein Framework automatisiert häufige Aufgaben | 35 |
1.2.1.2 Ein Framework bietet eine Architekturlösung | 36 |
1.2.2 Warum man mit einem Framework arbeiten sollte | 36 |
1.3 Das Framework von Struts 2 | 37 |
1.3.1 Ein kurzer historischer Abriss | 37 |
1.3.2 Struts 2 aus 10.000 Metern Höhe: Das MVC-Muster | 38 |
1.3.2.1 Controller – FilterDispatcher | 39 |
1.3.2.2 Model – Action | 40 |
1.3.2.3 View – Result | 40 |
1.3.3 Wie Struts 2 arbeitet | 41 |
1.3.3.1 Interceptors | 42 |
1.3.3.2 Der ValueStack und OGNL | 43 |
1.4 Zusammenfassung | 45 |
2 Struts 2 – Der erste Kontakt | 47 |
2.1 Deklarative Architektur | 48 |
2.1.1 Zwei Arten der Konfiguration | 48 |
2.1.1.1 Die Konfiguration des Frameworks selbst | 48 |
2.1.1.2 Deklaration der Architektur Ihrer Anwendung | 48 |
2.1.2 Zwei Mechanismen zur Deklaration der Architektur | 49 |
2.1.2.1 Die XML-basierte deklarative Architektur | 50 |
2.1.2.2 Die auf Java-Annotationen basierende deklarative Architektur | 51 |
2.1.2.3 Welche Methode sollten Sie nehmen? | 52 |
2.1.3 Intelligente Defaults | 52 |
2.2 Hello auf die Schnelle | 53 |
2.2.1 Deployment der Beispielanwendung | 53 |
2.2.1.1 Das Layout einer Struts-2-Webanwendung | 55 |
2.2.2 Die HelloWorld-Anwendung | 58 |
2.2.2.1 Benutzerleitfaden für HelloWorld | 58 |
2.2.2.2 Die Details von HelloWorld | 59 |
2.3 HelloWorld mit Annotationen | 65 |
2.4 Zusammenfassung | 68 |
Teil 2: Zentrale Konzepte: Actions, Interceptors und Typkonvertierungen | 69 |
3 Die Arbeit mit Actions | 71 |
3.1 Die Actions in Struts 2 | 72 |
3.1.1 Was macht eine Action? | 72 |
3.1.1.1 Actions kapseln den Unit of Work | 72 |
3.1.1.2 Actions bieten einen Ort für den Datentransfer | 73 |
3.1.1.3 Actions geben Control-String fürs Result-Routing zurück | 74 |
3.2 Verpacken der Actions | 74 |
3.2.1 Das Struts 2 Portfolio | 75 |
3.2.2 Die Organisation der Pakete | 75 |
3.2.3 Die Arbeit mit den Komponenten des struts-default-Pakets | 78 |
3.3 Implementierung von Actions | 80 |
3.3.1 Das optionale Action-Interface | 81 |
3.3.2 Die ActionSupport-Klasse | 82 |
3.3.2.1 Einfache Validierung | 83 |
3.3.2.2 Ressourcenbündel für Nachrichtentext | 88 |
3.4 Daten auf Objekte transferieren | 90 |
3.4.1 Objekt-gepufferte JavaBeans-Properties | 91 |
3.4.2 ModelDriven-Actions | 93 |
3.4.3 Domänenobjekte für Datentransfer – Eine Abschlussbemerkung | 95 |
3.5 Dateiupload – Eine Fallstudie | 96 |
3.5.1 Eingebauter Support über das Paket struts-default | 97 |
3.5.2 Was macht der fileUpload-Interceptor? | 97 |
3.5.3 Der Beispielcode von Struts 2 Portfolio | 98 |
3.5.3.1 Mehrere Dateien und andere Einstellungen | 101 |
3.6 Zusammenfassung | 101 |
4 Den Workflow mit Interceptors ergänzen | 103 |
4.1 Abfangen von Anfragen | 104 |
4.1.1 Das MVC aufräumen | 104 |
4.1.2 Die Vorteile einfahren | 106 |
4.1.3 Erstellen von Interceptors | 107 |
4.2 Interceptors im Einsatz | 108 |
4.2.1 Die Chefin: ActionInvocation | 108 |
4.2.2 Wie die Interceptors feuern | 108 |
4.3 Die in Struts 2 integrierten Interceptors | 111 |
4.3.1 Utility-Interceptors | 112 |
4.3.1.1 timer | 112 |
4.3.1.2 logger | 112 |
4.3.2 Interceptors für den Datentransfer | 112 |
4.3.2.1 params (defaultStack) | 113 |
4.3.2.2 static-params (defaultStack) | 113 |
4.3.2.3 autowiring | 113 |
4.3.2.4 servlet-config (defaultStack) | 114 |
4.3.2.5 fileUpload (defaultStack) | 114 |
4.3.3 Workflow-Interceptor | 114 |
4.3.3.1 workflow (defaultStack) | 115 |
4.3.3.2 validation (defaultStack) | 117 |
4.3.3.3 prepare (defaultStack) | 117 |
4.3.3.4 modelDriven (defaultStack) | 118 |
4.3.4 Weitere Interceptors | 119 |
4.3.4.1 exception (defaultStack) | 119 |
4.3.4.2 token und token-session | 120 |
4.3.4.3 scoped-modelDriven (defaultStack) | 120 |
4.3.4.4 execAndWait | 120 |
4.3.5 Integrierte Stacks | 121 |
4.4 Deklaration von Interceptors | 121 |
4.4.1 Deklaration einzelner Interceptors und Interceptor-Stacks | 122 |
4.4.1.1 Die Struktur der XML-Dokumente | 124 |
4.4.2 Interceptors auf Actions mappen | 124 |
4.4.3 Setzen und Überschreiben von Parametern | 125 |
4.5 Erstellen eigener Interceptors | 126 |
4.5.1 Implementierung des Interceptor-Interface | 126 |
4.5.2 Der AuthenticationInterceptor | 127 |
4.6 Zusammenfassung | 131 |
5 Datentransfer – OGNL und Typkonvertierung | 133 |
5.1 Datentransfer und Typkonvertierung: Übliche Aufgaben bei Webanwendungen | 134 |
5.2 OGNL und Struts 2 | 135 |
5.2.1 Die Aufgabe von OGNL | 135 |
5.2.1.1 Die Ausdruckssprache | 135 |
5.2.1.2 Typkonverter | 137 |
5.2.2 Wie passt OGNL in das Framework? | 137 |
5.2.2.1 Eingehende Daten | 138 |
5.2.2.2 Ausgehende Daten | 140 |
5.3 Integrierte Typkonverter | 140 |
5.3.1 Konvertierungen out of the box | 141 |
5.3.2 Formularfeldnamen mit OGNL-Ausdrücken auf Properties mappen | 142 |
5.3.2.1 Primitive und Wrapper-Klassen | 142 |
5.3.2.2 Bearbeitung von Anfrageparametern mit mehreren Werten | 144 |
5.3.2.3 Arrays | 145 |
5.3.2.4 Lists | 147 |
5.3.2.5 Maps | 152 |
5.4 Eigene Typkonvertierungen | 155 |
5.4.1 Implementierung eines Typkonverters | 156 |
5.4.2 Konvertierung zwischen Strings und Circles | 157 |
5.4.3 Konfiguration des Frameworks zur Arbeit mit dem Konverter | 158 |
5.4.3.1 Property-spezifisch | 158 |
5.4.3.2 Globale Typkonverter | 160 |
5.5 Zusammenfassung | 160 |
Teil 3: Die View erstellen – Tags und Results | 162 |
6 Die View erstellen – Tags | 165 |
6.1 Auf die Plätze … | 166 |
6.1.1 Der ActionContext und OGNL | 166 |
6.1.1.1 Die Wahl des Root-Objekts für OGNL | 169 |
6.1.2 Der ValueStack – Ein virtuelles Objekt | 170 |
6.2 Die Tags von Struts im Überblick | 172 |
6.2.1 Die Syntax der Tag-API von Struts 2 | 172 |
6.2.1.1 Die Syntax von JSP | 173 |
6.2.1.2 Die Syntax von Velocity | 173 |
6.2.1.3 Die Syntax von FreeMarker | 174 |
6.2.2 Attribute für Tags mit OGNL setzen | 174 |
6.2.2.1 String- und Nicht-String-Attribute | 175 |
6.2.2.2 Erzwingen einer OGNL-Auflösung | 176 |
6.3 Daten-Tags | 177 |
6.3.1 Das property-Tag | 178 |
6.3.2 Das set-Tag | 178 |
6.3.3 Das push-Tag | 180 |
6.3.4 Das bean-Tag | 181 |
6.3.5 Das action-Tag | 184 |
6.4 Control-Tags | 186 |
6.4.1 Das iterator-Tag | 186 |
6.4.1.1 Die Verwendung von IteratorStatus | 187 |
6.4.2 Die Tags if und else | 188 |
6.5 Verschiedene andere Tags | 188 |
6.5.1 Das include-Tag | 189 |
6.5.2 Das URL-Tag | 190 |
6.5.3 Die Tags i18n und text | 191 |
6.5.4 Das param-Tag | 193 |
6.6 Die Verwendung von JSTL und anderen nativen Tags | 194 |
6.7 Kurze Einführung in die Ausdruckssprache OGNL | 194 |
6.7.1 Was ist OGNL? | 194 |
6.7.2 Häufige Features einer Ausdruckssprache in Struts 2 | 195 |
6.7.2.1 Referenzieren von Bean-Properties | 195 |
6.7.2.2 Setting oder Getting? | 196 |
6.7.2.3 Die Arbeit mit Java Collections | 197 |
6.7.2.4 Die Arbeit mit Lists und Arrays | 197 |
6.7.2.5 Die Arbeit mit Maps | 198 |
6.7.2.6 Collections filtern und projizieren | 200 |
6.7.3 Fortgeschrittene Features der Ausdruckssprache | 201 |
6.7.3.1 Literale und Operatoren | 201 |
6.7.3.2 Aufrufen von Methoden | 203 |
6.7.3.3 Zugriff auf statische Methoden und Felder | 203 |
6.8 Zusammenfassung | 204 |
7 UI-Komponenten-Tags | 207 |
7.1 Warum wir UI-Komponenten-Tags brauchen | 208 |
7.1.1 Mehr als nur Formularelemente | 208 |
7.1.1.1 HTML-Markup generieren | 209 |
7.1.1.2 Binden von Formularfeldern an ValueStack-Properties | 210 |
7.1.1.3 Integration von Typkonvertierung, Validierung und Internationalisierung | 214 |
7.2 Tags, Templates und Themes | 214 |
7.2.1 Tags | 216 |
7.2.2 Templates | 216 |
7.2.3 Themes | 217 |
7.2.3.1 Das Theme ändern | 218 |
7.3 Referenz der Tags der UI-Komponenten | 219 |
7.3.1 Allgemeine Attribute | 219 |
7.3.2 Einfache Komponenten | 221 |
7.3.2.1 Die head-Komponente | 221 |
7.3.2.2 Die form-Komponente | 222 |
7.3.2.3 Die textfield-Komponente | 227 |
7.3.2.4 Die password-Komponente | 229 |
7.3.2.5 Die textarea-Komponente | 230 |
7.3.2.6 Die checkbox-Komponente | 230 |
7.3.3 Von Collections gepufferte Komponenten | 233 |
7.3.3.1 Die select-Komponente | 233 |
7.3.3.2 Die radio-Komponente | 238 |
7.3.3.3 Die checkboxlist-Komponente | 239 |
7.3.3.4 Vorbelegung mit von Collections gepufferten Komponenten | 240 |
7.3.4 Bonus-Komponenten | 242 |
7.3.4.1 Die label-Komponente | 242 |
7.3.4.2 Die hidden-Komponente | 242 |
7.3.4.3 Die doubleselect-Komponente | 243 |
7.4 Zusammenfassung | 244 |
8 Results unter der Lupe | 247 |
8.1 Leben nach der Action | 248 |
8.1.1 Jenseits der Seite – Wie man mit eigenen Results Ajax-Anwendungen in Struts 2 erstellt | 249 |
8.1.2 Implementierung eines JSON-Result-Typs | 250 |
8.1.2.1 Ein Ajax-Client als Demo für unser Result | 251 |
8.1.2.2 Programmieren des JSONResults | 252 |
8.1.2.3 Ein Ajax-Client | 255 |
8.1.2.4 Die Action | 256 |
8.1.2.5 Deklaration und Verwendung des Typs JSONResult | 257 |
8.2 Häufig verwendete Result-Typen | 259 |
8.2.1 Der RequestDispatcher alias Dispatcher | 260 |
8.2.1.1 Der Servlet-Kern des DispatcherResults | 260 |
8.2.1.2 Normaler Workflow: Dispatching als forward() | 261 |
8.2.1.3 An ein anderes Servlet weiterleiten | 262 |
8.2.1.4 Dispatching als ein include() | 265 |
8.2.1.5 Einrichten eines RequestDispatcher-Results | 265 |
8.2.2 Das ServletRedirectResult alias redirect | 266 |
8.2.2.1 Einrichten eines Umleitungs-Results | 267 |
8.2.2.2 OGNL zum Erstellen dynamischer Standorte einbetten | 268 |
8.2.3 Das ServletActionRedirectResult alias redirectAction | 269 |
8.3 JSP-Alternativen | 271 |
8.3.1 VelocityResult alias velocity | 271 |
8.3.1.1 Die Arbeit mit Velocity-Results | 272 |
8.3.2 FreemarkerResult alias freemarker | 273 |
8.3.2.1 Die Arbeit mit FreeMarker-Results | 274 |
8.4 Globale Results | 275 |
8.5 Zusammenfassung | 276 |
Teil 4: Optimieren der Anwendung | 277 |
9 Integration mit Spring und Hibernate/JPA | 279 |
9.1 Warum bei Struts 2 mit Spring arbeiten? | 280 |
9.1.1 Wofür ist Abhängigkeitsinjektion gut? | 280 |
9.1.1.1 Eng gekoppelte Objekte | 281 |
9.1.2 Wie Spring Objekte verwaltet und Abhängigkeiten injiziert | 283 |
9.1.3 Mit Interfaces Implementierungen verstecken. | 284 |
9.2 Spring in Struts 2 einfügen | 287 |
9.2.1 Spring verwaltet die Erstellung von Actions, Interceptors und Results | 288 |
9.2.2 Autowiring zur Injektion von Abhängigkeiten in Actions, Interceptors und Results | 290 |
9.2.2.1 Autowiring nach name | 291 |
9.2.2.2 Autowiring nach type, constructor und auto | 292 |
9.3 Warum soll man bei Struts 2 die Java Persistence API nutzen? | 294 |
9.3.1 Das Projekt für JPA mit Hibernate einrichten | 294 |
9.3.1.1 Die Liste der passenden JAR-Dateien | 294 |
9.3.1.2 Die Wahl der Datenbank | 295 |
9.3.1.3 Mit Spring die JPA-Abhängigkeiten verwalten | 295 |
9.3.1.4 Lazy Loading mit dem OpenEntityManagerInView-Filter von Spring | 297 |
9.3.2 Programmieren einer von Spring verwalteten JPA | 299 |
9.3.2.1 Die Persistenzeinheit | 299 |
9.3.2.2 Mit Annotationen die Java-Klassen auf Datenbanktabellen mappen | 300 |
9.3.2.3 Mit dem JPA-EntityManager das Serviceobjekt implementieren | 301 |
9.4 Zusammenfassung | 303 |
10 Das Validierungsframework | 305 |
10.1 Das Validierungsframework | 306 |
10.1.1 Die Architektur des Validierungsframeworks | 306 |
10.1.1.1 Die Domänendaten | 306 |
10.1.1.2 Validierungsmetadaten | 307 |
10.1.1.3 Validatoren | 307 |
10.1.2 Das Validierungsframework im Workflow von Struts 2 | 308 |
10.1.2.1 Die grundlegende Validierung | 308 |
10.1.2.2 Der Workflow des Validierungsframeworks | 309 |
10.2 Actions zur Validierung verschalten | 311 |
10.2.1 Deklaration der Validierungsmetadaten mit ActionClassvalidations.xml | 312 |
10.2.1.1 Feld-Validatoren | 314 |
10.2.1.2 Nicht-Feld-Validatoren | 314 |
10.2.1.3 Optionen für Nachrichtenelemente | 315 |
10.2.2 Die integrierten Validatoren | 316 |
10.3 Eigene Validatoren schreiben | 318 |
10.3.1 Mit eigenem Validator die Passwortstärke prüfen | 318 |
10.3.2 Die Arbeit mit dem eigenen Validator | 321 |
10.4 Fortgeschrittene Themen des Validierungsframeworks | 322 |
10.4.1 Validierung auf der Ebene des Domänenobjekts | 322 |
10.4.2 Mit Validierungskontext die Validierungen verfeinern | 326 |
10.4.2.1 Den Validierungskontext mit dem Validator visitor und Domänenobjekten verwenden | 327 |
10.4.3 Vererbung der Validierung | 329 |
10.4.4 Vorzeitiges Beenden von Validierungen | 329 |
10.4.5 Validierungen mit Annotationen deklarieren | 330 |
10.5 Zusammenfassung | 332 |
11 Die Internationalisierung | 335 |
11.1 Java-i18n und das Framework von Struts 2 | 336 |
11.1.1 Auslesen von lokalisiertem Text mit ResourceBundle und Locale | 337 |
11.1.1.1 Ressourcen in einem ResourceBundle speichern | 337 |
11.1.1.2 Die Arbeit mit nativen Java-ResourceBundles | 338 |
11.1.2 Wie Struts 2 die Arbeit mit i18n erleichtert | 340 |
11.2 Eine i18n-Demo für Struts 2 | 341 |
11.2.1 Eine kurze Demo für Struts 2 und i18n | 341 |
11.2.2 Ein kurzer Blick hinter die Kulissen | 343 |
11.3 i18n bei Struts 2 – Die Details | 345 |
11.3.1 Der Default-Lokalisierungsalgorithmus von Struts 2 | 345 |
11.3.1.1 Die Spezifizität der Sprach- und Ländereinstellungen und das Auslesen von Nachrichten | 348 |
11.3.1.2 Definition von Default-Bundles | 349 |
11.3.2 Nachrichtentexte aus den Bundles auslesen | 350 |
11.3.2.1 Auslesen der richtigen Sprache | 350 |
11.3.2.2 Das key-Attribut der UI-Komponenten-Tags | 351 |
11.3.2.3 Lokalisieren der Fehlermeldungen für die Validierung | 352 |
11.3.2.4 Lokalisieren der Fehlermeldungen aus der Typkonvertierung | 353 |
11.3.3 Ein Bundle über das i18n-Tag angeben | 354 |
11.3.4 Parametrisierung der lokalisierten Texte | 354 |
11.3.4.1 Parametrisierung von Nachrichtentexten mit OGNL-Ausdrücken | 355 |
11.3.4.2 Parametrisierung der Nachrichtentexte mit nativen Java-Fähigkeiten | 355 |
11.3.5 Formatierung von Datumsangaben und Zahlen | 356 |
11.4 Überschreiben der Default-Erkennung des Gebietsschemas | 357 |
11.4.1 Interaktives Setzen von Sprach- und Ländereinstellungen | 358 |
11.4.1.1 Der i18n-Interceptor | 358 |
11.4.2 Sprach- und Ländereinstellungen programmatisch setzen | 360 |
11.5 Zusammenfassung | 361 |
Teil 5: Fortgeschrittene Themen und Best Practices | 363 |
12 Struts 2 mit Plug-ins erweitern | 365 |
12.1 Plug-ins – Ein Überblick | 366 |
12.1.1 Wie man Plug-ins findet | 367 |
12.2 Bekannte Plug-ins | 367 |
12.2.1 SiteMesh | 368 |
12.2.2 Tiles | 369 |
12.2.3 JFreeChart | 371 |
12.3 Das interne Komponentensystem | 373 |
12.3.1 Beans | 373 |
12.3.2 Konstanten | 374 |
12.3.3 Injektion | 374 |
12.3.4 Interne Erweiterungspunkte von Struts | 375 |
12.4 Ein Breadcrumb-Plug-in schreiben | 377 |
12.5 Zusammenfassung | 381 |
13 Best Practices | 383 |
13.1 Die Umgebung einrichten | 384 |
13.1.1 Die IDE einrichten | 384 |
13.1.2 Ressourcen erneut laden | 385 |
13.2 Unit-Tests für Ihre Actions | 385 |
13.2.1 Der Vorteil von IoC für Tests | 386 |
13.2.2 JUnit und die Tests | 387 |
13.2.3 Tests von validation.xml-Dateien | 389 |
13.3 Die Wiederverwendbarkeit maximieren | 390 |
13.3.1 Komponenten mit dem component-Tag erstellen | 391 |
13.3.2 Arbeit mit den Template-Tags | 392 |
13.3.3 Verbindung der Punkte von der UI zu den Objekten | 393 |
13.4 Fortgeschrittene Verwendung der UI-Tags | 394 |
13.4.1 Überschreiben vorhandener Templates | 394 |
13.4.2 Eigene Templates schreiben | 395 |
13.4.3 Eigene Themes schreiben | 395 |
13.4.3.1 Ein Theme von Grund auf neu erstellen (schwer!) | 395 |
13.4.3.2 Ein vorhandenes Theme wrappen | 396 |
13.4.3.3 Ein vorhandenes Theme erweitern | 396 |
13.5 Zusammenfassung | 396 |
14 Migration von Struts Classic | 397 |
14.1 Der Wissenstransfer aus Struts Classic | 397 |
14.1.1 Actions | 398 |
14.1.2 Wo sind die ActionForms geblieben? | 399 |
14.1.3 Austausch der Tag-Libraries | 401 |
14.1.4 Verteilen der Nachrichtenressourcen | 403 |
14.2 Schrittweise Konvertierung | 405 |
14.2.1 Rom schrittweise erobern | 406 |
14.2.2 Die Action-Mappings | 407 |
14.2.3 Wo die Action das Formular trifft | 409 |
14.2.4 Die Seite wandeln | 410 |
14.2.5 No speak English | 413 |
14.2.6 Die Datenpolizei | 414 |
14.2.7 Könnten wir nicht einfach so klarkommen? | 416 |
14.3 Zusammenfassung | 418 |
15 Themen für Fortgeschrittene | 419 |
15.1 Fortgeschrittene Verwendung von Actions | 419 |
15.1.1 Alternative Methodenaufrufe | 420 |
15.2 Dynamische Methodenaufrufe | 421 |
15.2.1 Die Methodenauswahl per Wildcard | 421 |
15.2.2 Dynamische Workflows | 424 |
15.3 Mit Tokens doppelte Formularübermittlungen verhindern | 425 |
15.3.1 Das -Formular-Tag | 425 |
15.3.2 Ausnahmen zur token-Interceptor-Regel | 427 |
15.4 Seiten mit Fortschrittsanzeige automatisch darstellen | 429 |
15.4.1 User am Rande des Nervenzusammenbruchs | 429 |
15.5 Eine einzige Action für CRUD-Operationen | 430 |
15.5.1 Dieses CRUD | 431 |
15.5.2 Interceptors und Interfaces | 432 |
15.5.3 Die Teile verbinden | 437 |
15.6 Tiles und Struts 2 | 439 |
15.6.1 Look & Feel der Website | 440 |
15.6.2 Konfiguration des Zusammenspiels | 441 |
15.6.3 Die Arbeit mit der deklarativen Architektur | 443 |
15.6.4 Vorbereiten der Inhalte einer Webseite mit einem Tiles-Controller | 445 |
15.7 Zusammenfassung | 447 |
Register | 449 |