Struts

Сomentários

Transcrição

Struts
Komponentenorientierte Softwareentwicklung
und Hypermedia
Prof. Dr. Frank Thiesing
Struts
Java-Framework
für Webapplikationen
Referenten:
Jens de Witt
Fabian Bartelt
Inhaltsverzeichnis
1.Was ist Struts?.......................................................................................................... 3
1.1.Einführung......................................................................................................... 3
2.Vorkenntnisse........................................................................................................... 3
2.1.HTTP-Protokoll.................................................................................................. 3
Das HTTP-Protokoll und der Request/Response-Kreislauf.................................4
HTTP-Header und HTTP-Antwortcodes.............................................................. 4
2.2.JavaBeans......................................................................................................... 4
3.Vorgeschichte: Servlet & JSPs................................................................................. 5
3.1.Dynamische Webseiten und Servlets................................................................ 5
3.2.Java Server Pages (JSP).................................................................................. 6
3.3.Taglibs............................................................................................................... 6
3.4.Das Model-View-Controller-Entwurfsmuster...................................................... 7
3.5.Was bedeutet Model 1 / Model 2 bei Webapplikationen?................................. 7
3.6.Komponenten des Struts-Frameworks.............................................................. 7
4.View-Komponenten................................................................................................... 8
4.1.JSP-Seiten & Taglibs......................................................................................... 9
4.2.Internationalisierung, I18N............................................................................... 10
4.3.ActionForms.................................................................................................... 10
4.4.Daten übergeben: Attribute............................................................................. 14
5.Modell-Komponenten.............................................................................................. 14
5.1.Die Klasse Action............................................................................................ 16
5.2.Steuerung der Applikation............................................................................... 18
struts-config.xml................................................................................................ 18
6.ausführliches Beispiel: eBay© für Arme (Menschen, nicht Körperteile)..................19
6.1.Anlegen einer neuen Struts-Webapplikation in Tomcat / die Datei web.xml... 19
6.2.Die struts-config.xml........................................................................................ 20
6.3.View-Beispiel: /form/editartikel.jsp................................................................... 21
7.Weitere Konzepte in Struts..................................................................................... 22
8.Fazit........................................................................................................................ 22
9.Anhang................................................................................................................... 23
9.1.Literatur........................................................................................................... 23
9.2.Links................................................................................................................ 23
1.
Was ist Struts?
1.1.
Einführung
Struts ist ein Framework für Webapplikationen. Struts baut auf der Java
Servlet-Spezifikation 2.3 auf. Es wird als Teilprojekt des Apache-Projekts
geführt.
Webapplikationen werden einerseits wegen des Internetbooms stark
nachgefragt (B2C, B2B). Aber auch für Unternehmen rechnet es sich,
plattformabhängige Applikationen durch Webapplikationen zu ersetzen, da
nur wartungsarme (daher kostengünstige) Webbrowser für solche
Applikationen auf Clientseite zur Verfügung stehen müssen. Serverseitig
muß andererseits ein erhöhter Wartungsaufwand in Kauf genommen
werden, was sich aber durch Kostenersparnisse bei der Clientseite
relativiert. (Als Beispiel ist das Mobilfunkunternehmen O2 zu nennen, die
viele betriebsinterne Applikationen auf Webbasis betreiben.)
Gängige Basisplattformen für Webapplikationen sind beispielsweise
herkömmliche CGI-Applikationen (auf C/C++-Basis), PHP, PERL. Verstärkt
durch die Popularität der Programmierplattform JAVA werden mitlwerweile
für professionelle Applikationen Java-Servlets und JSP genommen, da diese
problemlos mit anderen JAVA-Anwendungen kommunizieren können (J2EE
mit EJBs als Referenzbeispiel genannt).
Mit Struts als Framework ist eine feste Grundstruktur auf MVC-Basis
bereitgestellt worden, die eine Webapplikation auf Servlet/JSP-Basis stark
strukturiert, leichter verständlich macht und gleichzeitig viele lästige
Standardaufgaben einer Applikationsentwicklung abnimmt.
2.
Vorkenntnisse
In diesem Kapitel werden Vorkenntnisse im Schnelldurchlauf vermittelt, die
zum Verständnis von Struts zwingend sind.
2.1.
HTTP-Protokoll
Das Hypertext-Transfer-Protokioll (HTTP) ist 1989 von Tim Berners-Lee und
seinen Mitstreitern am CERN Institut entwickelt worden. HTTP ist ein
Protokoll auf der Anwendungsebene (7 Schichten Modell), es ist zustandslos
und funktioniert nach einem simplen Anfrage/Antwort-Schema.
Das HTTP-Protokoll und der Request/Response-Kreislauf
Die Vorgehensweise des HTTP-Protokolls sieht wie folgt aus:
Ein HTTP-Client baut eine Verbindung zum HTTP-Server über dessen TCPPort auf, i.d.R. Port-Nummer 80. Danach sendet der Client einen Request an
den Server. (Z. B. GET /index.html HTTP/1.1) Der HTTP-Server sendet
einen Response als Antwort, die das gewünschtes Dokument und HTTPHeader (Steuerinformationen) enthält. Der Server baut die Verbindung ab.
HTTP-Header und HTTP-Antwortcodes
Der HTTP-Header enthält Steuerinformationen, die zwischen einem Browser
und einem HTTP-Server ausgetauscht werden. Sie stellen Informationen
bereit, wie z.B. den Typ des Browsers, die Anzahl der gesendeten Zeichen,
den Datentyp und den Antwortcode. Der Antwortcode teilt dem Browser den
Status der Anforderung mit. Es gibt folgende Kategorien von Antwortcodes:

1xx: Zeigen Informationen über den Status der Anforderung. Wird vom
HTTP 1.1 nicht verwendet.

2xx: Die Anforderungen wurden vom Server verstanden und akzeptiert.

3xx: Die angeforderte Ressource findet sich an einer anderen Stelle.

4xx: Fehler auf Seiten des Clients.

5xx: Fehler auf Seiten des Servers
2.2.
JavaBeans
Die JavaBeans definieren wiederverwendbare, einbettbare, modulare
Software-Komponenten. Wichtige Merkmale von Beans sind:

Selbstbeobachtung (Introspection): Eine Klasse lässt sich von außen
auslesen. So kann ein spezielles Programm, wie das BDK oder eine
visuelle Entwicklungsumgebung, eine Bean analysieren und ihre
Eigenschaften abfragen. Auch umgekehrt kann eine Bean herausfinden,
ob sie etwa gerade von einem grafischen Entwicklungswerkzeug
modelliert wird oder in einer Applikation ohne GUI Verwendung findet.

Eigenschaften (Properties): Attribute beschreiben den Zustand des
Objekts. In einem Modellierungswerkzeug lassen diese sich ändern. Im
BDK standen die Eigenschaften etwa in dem Property-Sheet. Da eine
Bean meistens eine grafische Komponente ist, besitzt sie etwa eine
Hintergrundfarbe. Diese Informationen können von außen durch
bestimmte Methoden abgefragt und verändert werden. Ändern wir hier
die Hintergrundfarbe im BDK, zeigt die Bean diese sofort an. Für alle
Eigenschaften werden spezielle Zugriffsmethoden definiert; sie werden
Property-Design-Pattern genannt.

Ereignisse (Events): Wir können die Komponente Ereignisse auslösen
lassen, sodass sie Zustandsänderungen und visuelle Interaktionen an
andere Beans oder Dienstprogramme weiterleitet. Grundlage für die
Ereignisbehandlung ist das Modell von Java 1.1 mit Auslösern und
Empfängern.

Anpassung (Customization): Der Bean-Entwickler kann die Eigenschaften
einer Bean visuell und interaktiv anpassen

Speicherung (Persistenz): Jede Bean kann ihren internen Zustand, also
die Eigenschaften, durch Serialisierung speichern und wiederherstellen.
So kann ein Builder-Tool die Komponenten laden und benutzen. Ein
spezieller Externalisierungsmechanismus erlaubt dem Entwickler die
Definition eines eigenen Speicherformats, zum Beispiel als XML-Datei
Zusätzlich zu den notwendigen Grundpfeilern lässt sich durch
Internationalisierung die Entwicklung internationaler Komponenten
vereinfachen. Verwendet eine Bean länderspezifische Ausdrücke, wie
Währungsformate oder Datumsformate, kann der Bean-Entwickler mit
länderunabhängigen Bezeichnern arbeiten, die dann in die jeweilige
Landessprache übersetzt werden.
3.
Vorgeschichte: Servlet & JSPs
3.1.
Dynamische Webseiten und Servlets
In der ersten Generation von Internet-Seiten war jede Seite statisch auf dem
Webserver abgelegt und durch einen eindeutigen Namen identifiziert.
Jedoch kam auch der Wunsch auf, Internetseiten dynamisch zu generieren.
Dies hat folgende Gründe:
•
Interaktion mit dem Betrachter der Website
•
Zugriff auf Datenbanken
Aus diesen Gründen wurden serverseitig Schnittstellen definiert, wobei die
bekannteste das Common Gateway Interface (kurz CGI) ist. Andere
Hersteller haben für ihre Server eigene Schnittstellen definiert. Mittels der
CGI-Schnittstelle kann der Browser dem Server Daten übergeben, wie etwa
ein Produkt, nach dem das Programm suchen soll. Auf der Server-Seite
laufen dann meist Programme, die in Skriptsprachen wie PHP oder Perl
geschrieben sind, die Aufbereitung der Daten übernehmen und die Antwort
an den Client zurücksenden.
Servlets sind nun die Antwort auf CGI-Programme. Dabei sind Servlets aber
nicht einfache Java-Programme, die über die CGI-Schnittstelle mit dem
Server kommunizieren, sondern eine eigenständige Entwicklung. Wenn wir
Java-Programme als normale Applikationen auf der Server-Seite nutzen
würden, müsste der Webserver immer dann, wenn eine dynamische Seite
generiert wird, die JVM aufrufen und dann das Programm ausführen. Eine
Verbesserung würde darin bestehen, dass der Webserver eine JVM
integriert, die immer läuft, und Objekte einzelne Verbindungen innerhalb der
Java-Maschine bedienen. Genau das sind Servlets. Sie sind vergleichbar mit
Applets. Ein Applet ist ein Java-Programm auf der Client-Seite (im Browser),
und ein Servlet ist ein Programm auf der Server-Seite (im Server).
Der Vorteil von Servlets liegt dabei verstärkt in der nun möglichen Interaktion
mit der JAVA-Welt, nun kann man mittels Webapplikationen entwickeln, die
auf JAVA-Objekte interaktiv zugreifen können. Die strenge Typisierung von
JAVA-Programmen hebt zusätzlich die Qualität von Webapplikationen auf
eine neue Qualität.
3.2.
Java Server Pages (JSP)
Servlets sind Server-Programme, die Webseiten erstellen. Das machen sie,
indem sie die HTML-Anweisungen mit println() in den Ausgabestrom der
ServletResponse senden.
Der Aufbau einer HTML-Seite mit println()-Anweisung in einem Servlet ist
daher sehr aufwändig. Außerdem fehlt eine Trennung zwischen Daten und
Visualisierung. Ändert sich das Erscheinungsbild, so muss das Programm
umgebaut werden. In vielen dynamischen Programmen stecken oft nur ein
oder zwei Zeilen Dynamik, der Rest ist statischer HTML-Code. In der Regel
ist der Programmierer auch nicht der Designer, und dieser möchte mit
Webseiten-Erstellungsprogrammen wie DreamWeaver oder Microsoft
FrontPage arbeiten.
Eine JSP (Java Server Pages) geht das Problem genau anders herum an.
Wo ein Servlet eine Java-Klasse ist, die sich um die Ausgabe des HTMLCodes kümmert, ist eine JSP eine HTML-Seite mit Java-Code ähnlich wie
eine php-Seite; eine JSP-Seite ist also ein umgestülptes Servlet.
Der Java-Code wird dabei eingerahmt in sogenannte Java-Scriplets.
3.3.
Taglibs
Eines der JSP-Entwicklung war schon immer die Neigung von
Programmierern, zu viele Java-Skriptlets auf ihren Seiten zu verwenden.
Dadurch sind die Seiten für einen HTML-Designer schwerer zu verstehen
und zu pflegen.
Die Antwort liegt in speziellen benutzerdefinierten Tags (engl. Custom tag
libraries). Diese Tags sind in XML formuliert, sodass es mit ihnen erstmals
möglich wird, eine Webseite ganz ohne Java-Scriptlets zu formulieren. Ein
XML-Prozessor kann eine generierte Datei mit Tags dann als korrektes XML
validieren.
Der Autor der Tags definiert nach außen eine Funktionalität ähnlich den
Beans. Den Nutzer hat es nicht zu interessieren, wie die Tags implementiert
sind. Wichtige Tag-Bibliotheken, sind die Standard Tag Library (JSTL) der
Apache-Gruppe und natürlich die struts-Tag-Bibliothek.
Eine wichtige Technik stellt dabei die JavaBeans-Technologie dar: die
Taglibs können mit JAVA-Objekten arbeiten, vorausgesetzt, dass alle
benötigten Klassenmethodensignaturen nach dem JavaBeans-Standard
kodiert sind.
3.4.
Das Model-View-Controller-Entwurfsmuster
Das MVC ist eines der bekanntesten Entwurfsmuster. Das MVC löst das
Entwurfsproblem für die drei Hauptfunktionen die in vielen Applikationen
auftreten:

Model: Verwalten der Daten in einer Datenbank oder auf einem
entfernten System

View: Erstellen der Darstellungsschicht für den Endbenutzer

Controller: Verwalten der Logik, die entscheidet, welche Bildschirme
dem Benutzer präsentiert werden, was im Fehlerfall passieren soll, und
wie und wann die Datenbank aktualisiert werden soll.
MVC löst dieses Problem, indem es den Code in drei einzelene Bereiche
aufteilt. Bei der Entwicklung von Webapplikationen werden die Views dabei
von JSP-Seiten dargestellt, als Controller fungieren dabei die Servlets. Als
Model können EJBs oder andere Applikationsobjekte verwendet werden.
3.5.
Was bedeutet Model 1 / Model 2 bei Webapplikationen?
Das Model 1 beschreibt die JSP-Verarbeitung, in der eine HTTPAnforderung (Request) direkt an eine JSP-Datei gesendet wird. Die gesamte
Verarbeitung erfolgt direkt in der JSP-Datei.
Das Model 2 ist anders. Es schickt den Request nicht zu einer JSP-Datei
sondern zu einem Servlet. Das Servlet sollte die für die Anforderung
erforderlichen Verarbeitungen ausführen und die Information dann in einem
Bean speichern. Das Bean wurde der JSP-Datei übergeben, die die
Information als Response dem Benutzer zurücksendet.
Client
Browser
Server
(1)
(2)
Controller
(Servlet)
Model
(Z.B. EJBs)
(3)
(4)
(5)
View
(JSP)
Zeichnung 1MVC-Model-2
3.6.
Komponenten des Struts-Frameworks
Das Struts-Framework erweitert das MVC-Model-2-Konzept um

Feste, leicht wartbare Grundstruktur

Dynamische Applikationskonfiguration (struts-config.xml)

Formularverarbeitung

Benutzerdefinierte Custom JSP-Tags zur Erstellung von JSP-Seiten
Es werden z.B. für Informationen über eine Person folgende Dateien
angelegt:

Person.java
Diese Klasse enthält das Datenmodell für eine Person. Es stellt einfache
Methoden bereit, die Daten anzugeben, abzufragen und diese persistent
zu speichern und dann wieder zu lesen.

PersonView.jsp
Wird für die Anzeige der Personeninformation verwendet.

PersonAction.java
Die Action-Klasse ist der Controller, der bei der Auswertung der
Personeinträge und der Auswahl der richtigen View hilft.
Die folgende Grafik zeigt beispielhaft das Zusammenspiel in Struts zwischen
Model, View, Controller und dem Struts-Framework. Auf die einzelnen
Komponenten gehen wir in den nächsten Kapiteln ausführlicher ein.
Client
Server
struts-config.xml
ActionForm
ActionServlet holt Konfiguration
von der struts-config.xml
(2) opt.
ActionServlet
Browser
(1)
(Controller)
(3)
Action
(Controller)
(4)
(5)
(6) Ausgabe
View
(JSP )
JSP-View holt Daten aus
übergebenen JavaBeans
Model
(JavaBeans)
Zeichnung 2Struts-MVC-Framework
4.
View-Komponenten
In Struts wird die View wie im MVC-Model-2 mit JSP-Seiten implementiert,
zusätzlich werden sogenannte ActionForms benutzt, die mit den JSP-Seiten
zusammenarbeiten.
Sie sind vom Konzept her am einfachsten zu verstehen, weil sie in gewissem
Ausmaß funktionieren wie die traditionellen Servlets oder reine JSPBenutzeroberflächen.
4.1.
JSP-Seiten & Taglibs
JSP-Seiten unter Struts sind genauso aufgebaut wie normale JSP-Seiten,
vorrangig verwenden diese jedoch die Struts-Taglibs. Funktionell beinhalten
diese:
•
erweiterte Tags zur Verarbeitung und Darstellung von Objekten
•
Darstellung von HTML-Formularen und Einbindung in das StrutsFramework
•
Formulargebundene Fehlerausgabe
•
Logik-Tags zur bedingten Darstellung von Informationen
Zum besseren Verständnis, ziehen wir ein Beispiel aus unserem Programm
heraus. (Unser Beispiel ist die Datei editUser.jsp aus unserem
Programmierbeispiel.)
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
<jsp:useBean id="editbenutzerForm" scope="request"
type="seminarstruts.form.EditbenutzerForm"/>
<html>
<head>
<meta name = "Generator"
content = "Easy Struts Xslt generator for Eclipse
(http://easystruts.sf.net).">
<title>
<logic:notEqual
name="editbenutzerForm"
property="benutzerId"
value="0">
Bearbeite Benutzeraccount
<bean:write name="editbenutzerForm"
property="name"/>'
</logic:notEqual>
<logic:equal
name="editbenutzerForm"
property="benutzerId"
value="0">
Registrierung für neuen Benutzer
</logic:equal>
</title>
</head>
<body>
<html:form action="/editbenutzerSubmit">
benutzerId :
<html:hidden property="benutzerId"/>
<html:errors property="benutzerId"/></br>
login :
<html:text property="login"/>
<html:errors property="login"/></br>
name :
<html:text property="name"/>
<html:errors property="name"/></br>
passwort :
<html:password property="passwort"/>
<html:errors property="passwort"/></br>
passwort2 :
<html:password property="passwort2"/>
<html:errors property="passwort2"/></br>
<html:submit/><html:cancel/>
</html:form>
<body>
</html>
Die JSP-Seite sieht einer HTML-Seite ähnlich, allerdings werden gleich am
Anfang die Namespaces für die struts Taglibs geladen (vergleichbar mit dem
import-Befehl in .java-Quellcodes). Die HTML-Tag werden zum Aufbau des
HTML-Formulars verwendet. Die JSP-Tags werden serverseitig verarbeitet,
bei der Ausgabe auf dem Browser (bzw. im Browser-Quelltext) sind diese
Tags nicht mehr sichtbar.
Interessant sind die bean- und die logic-Tags. Mit <logic:notEqual> wird
überprüft, die in den ActionForm-Bean abgelegten Daten zu einem neuen
oder zu einem existierenden Benutzer gehören. Existiert ein Benutzer, so
wird der Benutzername in der Titelzeile des Browsers angezeigt. Anderfalls
wird „Neuer Benutzer“ ausgegeben.
Das <html:errors>-Tag wird zur Fehlerausgabe benutzt, die während der
Validierung von Formulardaten (in ActionForm-Beans) bzw. in den ActionKlassen aufgetreten sind.
Wird es mit dem Attribut verwendet, zeigt es nur die Fehler für die
betreffende Eigenschaft an. Es gibt zwei spezielle Werte, die Sie in Ihre
Datei ApplicationResources.properties schreiben können, um zu steuern, wie
diese Fehler angezeigt werden:
errors.header=<FONT COLOR="#ff0000">
errors.footer=</BR></FONT>
Der Wert von errors. header wird unmittelbar vor dem Fehler ausgegeben;
der f ooter wird nach dem Fehler ausgegeben. In diesem Beispiel wird der
Fehler rot dargestellt.
4.2.
Internationalisierung, I18N
Um die Fehlermeldungen aus einer Formularauswertung internationalisieren
zu können, wird das Tag bean:message in die JSP-Seite eingebaut. Dieses
Tag sucht nach einem Wert in dem angegebenen Resource-Bundle
(standardmäßig ApplicationResources.properties) und sendet ihn an den
Browser.
Auch in Verbindung mit dem <html:errors>-Tag wird dieser Mechanismus
verwendet.
4.3.
ActionForms
Die JSP-Seiten und ActionForm-Beans arbeiten in Struts Hand in Hand: Die
JSP geben die Benutzereingaben an das Bean weiter, das Bean validiert die
Daten und gibt Auswertungsfehler an die JSP zurück.
Um zu verstehen, wie sie zusammenarbeiten, betrachten wir ein ActionForm
und die zugehörige JSP-Seite. Das Listing zeigt das Bean EditbenutzerForm.
Dieses Bean wird zum Anlegen oder Bearbeiten von Benutzerdaten benutzt:
package seminarstruts.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
/**
* EditbenutzerForm.java created by EasyStruts - XsltGen.
* http://easystruts.sf.net
* created on 06-04-2004
*
* XDoclet definition:
* @struts:form name="editbenutzerForm"
*/
public class EditbenutzerForm extends ActionForm {
// --------------------------------------------------------Instance Variables
/** passwort property */
private String passwort;
/** passwort2 property */
private String passwort2;
/** login property */
private String login;
/** benutzerId property */
private String benutzerId;
/** name property */
private String name;
// --------------------------------------------------------Methods
/**
* Method validate
* @param ActionMapping mapping
* @param HttpServletRequest request
* @return ActionErrors
*/
public ActionErrors validate(
ActionMapping mapping,
HttpServletRequest request) {
throw new UnsupportedOperationException("Generated
method 'validate(...)' not implemented.");
}
/**
* Method reset
* @param ActionMapping mapping
* @param HttpServletRequest request
*/
public void reset(ActionMapping mapping, HttpServletRequest
request) {
passwort = "";
passwort2 = "";
login = "";
benutzerId = "";
name = "";
}
/**
* Returns the passwort.
* @return String
*/
public String getPasswort() {
return passwort;
}
/**
* Set the passwort.
* @param passwort The passwort to set
*/
public void setPasswort(String passwort) {
this.passwort = passwort;
}
/**
* Returns the passwort2.
* @return String
*/
public String getPasswort2() {
}
return passwort2;
/**
* Set the passwort2.
* @param passwort2 The passwort2 to set
*/
public void setPasswort2(String passwort2) {
this.passwort2 = passwort2;
}
/**
* Returns the login.
* @return String
*/
public String getLogin() {
return login;
}
/**
* Set the login.
* @param login The login to set
*/
public void setLogin(String login) {
this.login = login;
}
/**
* Returns the benutzerId.
* @return String
*/
public String getBenutzerId() {
return benutzerId;
}
/**
* Set the benutzerId.
* @param benutzerId The benutzerId to set
*/
public void setBenutzerId(String benutzerId) {
this.benutzerId = benutzerId;
}
/**
* Returns the name.
* @return String
*/
public String getName() {
return name;
}
}
/**
* Set the name.
* @param name The name to set
*/
public void setName(String name) {
this.name = name;
}
Dieses ActionForm-Bean (und die meisten anderen Struts-bezogenen
Dateien in der Applikation) wurden unter Verwendung von EasyStruts für
Eclipse erzeugt, der automatisch ActionForms, Actions und JSP-Dateien für
Struts erzeugt.
Der hintere Teil der Datei kann größtenteils ignoriert werden. Er enthält die
Get-und Set-Methoden für die Bean-Eigenschaften, wie in jedem anderen
JavaBean.
Die beiden wichtigsten Methoden der Klasse sind reset() und validate().
Wenn ein Formular vor der Verwendung durch Struts initialisiert wird, wird
die Methode reset() aufgerufen. Sie ist dafür verantwortlich, alle BeanEigenschaften auf ihre Ausgangswerte zurückzusetzen. (Es findet eine
Wiederverwertung von ActionForms statt, um Ressourcen zu sparen.)
Die Methode validate() wertet die vom Benutzer in dem Formular
vorgenommenen Eingaben aus und stellt sicher, dass sie konsistent mit den
Daten sind, die die Anwendung braucht (korrekte Syntax der
Formulareingaben).
Der Methode validate() werden zwei Argumente übergeben: ActionMapping
für die Aktion und HttpServletRequest. Die Methode gibt ein ActionErrorsObjekt zurück, das eine Auflistung aller ActionError-Objekte darstellt, die
während der Auswertung erzeugt werden. ActionError-Objekte aktivieren die
<html:errors>-Tags, die die Fehlermeldung darstellt.
Ein ActionError-Objekt speichert dabei einen Schlüssel, die eigentliche
Meldung wird über den MessageResources-Mechanismus (also über die
I18N) geholt (siehe oben).
4.4.
Daten übergeben: Attribute
Nun muß noch nebenbei geklärt werden, wie überhaupt die Daten innerhalb
einer Webapplikation gespeichert werden und übergeben werden.
Daten werden in Servlets und in JSP-Seiten zur Übergabe in sogenannte
Attribute gespeichert, die sich in verschiedenen Scopes befinden können:
Scope
Code (Servlet)
Code (JSP)
request
request.getAttribute("attr")
request.
setAttribute("attr",x)
<jsp:writeBean
name=“attr“
property=“prop“
scope=“request“/>
response
Response.
getAttribute("attr")
Response.
setAttribute("attr",x)
<jsp:writeBean
name=“attr“
property=“prop“
scope=“response“/>
session
request.getSession().
getAttribute("attr")
request.getSession().
setAttribute("attr",x)
<jsp:writeBean
name=“attr“
property=“prop“
scope=“session“/>
application
request.getSession().
getAttribute("attr")
request.getSession().
setAttribute("attr",x)
<jsp:writeBean
name=“attr“
property=“prop“
scope=“application“/>
Der Lebenszyklus und die Erreichbarkeit eines Attributes definieren sich
dabei durch den Scope, d.h. Ein Session-Attribut lebt solange wie die
Session existiert, kann aber nicht aus anderen Sessions heraus ausgelesen
werden.
Ein request-Attribut lebt nur solange, wie die einzelne Browseranforderung
läuft. Auch dieses ist nicht durch andere Request auslesbar.
5.
Modell-Komponenten
Die Modell-Komponente wird verwendet, um den Zugriff auf die
entsprechende Geschäftslogik der Anwendung zu erhalten und zu steuern.
Als Model können eigene Klassen verwendet werden, es können aber auch
EJBs oder andere Persistence Layers verwendet werden: Grundbedingung
ist, dass die Klassen get- und set- Methoden nach der JavaBeansSpezifikation definieren. Diese werden unbedingt für die JSP-Seiten
benötigt, die Taglibs (JSTL und Struts-Taglibs) arbeiten mit diesen get- und
set- Methoden.
In den hier verwendeten Beispiel wurde zur Generierung der
Datenbankklassen der Persistence Layer Torque verwendet. Es ist Teil des
apache Java-Plattform. Als Beispiel wird hier die Benutzer-Klasse
verwendet.
package seminarstruts.model;
import org.apache.torque.om.Persistent;
import java.util.List;
import java.util.Vector;
import org.apache.torque.TorqueException;
import org.apache.torque.util.Criteria;
/**
* The skeleton for this class was autogenerated by Torque on:
*
* [Tue Jun 01 21:50:33 CEST 2004]
*
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*/
public class Benutzer
extends seminarstruts.model.BaseBenutzer
implements Persistent
{
}
/**
* The skeleton for this class was autogenerated by Torque on:
*
* [Tue Jun 01 21:50:33 CEST 2004]
*
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*/
public class BenutzerPeer
extends seminarstruts.model.BaseBenutzerPeer
{
public static Benutzer getBenutzerByLogin(String log)
{
Criteria crit=new Criteria();
crit.add(LOGIN,log);
List l;
try {
l = doSelect(crit);
} catch (TorqueException e) {
// TODO Auto-generated catch block
e.printStackTrace();
l=new Vector();
}
if (l.size()==1) return (Benutzer) l.get(0);
else return null;
}
}
Und die dazugehörige BenutzerPeer-Klasse, die die direkte Kommunikation
mit der Datenbank enthält. Dazu gehören noch die BaseBenutzer-Klasse
und die BaseBenutzerPeer-Klasse, die schon gewisse Grundfunktionalitäten
wie Benutzer Daten speichern, löschen und editieren enthalten: dabei sind
die get- und set- Methoden nach der JavaBeans-Spezifikation kodiert.
In Struts wird die benutzerspezifische Controller-Logik nicht in einem Servlet
implementiert, sondern in separaten 'Action'-Klassen.
Das bei Struts beiliegende ActionServlet ruft diese Action-Klassen auf.
Optional kann ein für die Action relevantes ActionForm-Bean vor dem Aufruf
einer Action-Klasse validiert werden; schlägt diese Validierung fehl, kann
automatisch eine JSP-Seite (oder auch eine andere Action) aufgerufen
werden.
Das Verhalten des ActionServlets wird über die Datei struts-config.xml
gesteuert.
5.1.
Die Klasse Action
Die Aufgabe des Controllers ist es mit den Daten, die der Benutzer eingibt,
etwas zu machen und zu entscheiden, was als nächstes geschehen soll.
In Struts wird der Controller in zwei Teilen implementiert: in den ActionKlassen und dem eigentlichen Struts Framework. Die Action nimmt Eingaben
vom Benutzer entgegen, koordiniert den Zugriff auf entfernte Systeme,
implementiert die Geschäftslogik und entscheidet, welche View-Komponente
dem Benutzer als nächstes angezeigt werden soll. Das Beispiel ist hier die
EditbenutzerAction-Klasse:
// Created by Xslt generator for Eclipse.
// XSL : not found (java.io.FileNotFoundException:
descriptor))
// Default XSL used :
easystruts.jar$org.easystruts.xslgen.JavaClass.xsl
(Bad file
package seminarstruts.action;
import seminarstruts.model.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import
import
import
import
org.apache.struts.action.Action;
org.apache.struts.action.ActionForm;
org.apache.struts.action.ActionForward;
org.apache.struts.action.ActionMapping;
import seminarstruts.form.EditbenutzerForm;
/**
* EditbenutzerAction.java created by EasyStruts - XsltGen.
* http://easystruts.sf.net
* created on 06-04-2004
*
* XDoclet definition:
* @struts:action validate="true"
* @struts:action-forward name="/form/editbenutzer.jsp"
path="/form/editbenutzer.jsp"
*/
public class EditbenutzerAction extends Action {
/**
* Method execute
* @param ActionMapping mapping
* @param ActionForm form
* @param HttpServletRequest request
* @param HttpServletResponse response
* @return ActionForward
* @throws Exception
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (!org.apache.torque.Torque.isInit())
return mapping.findForward("noDatabase");
EditbenutzerForm bform=new EditbenutzerForm();
int log=0;
try {
log =
Integer.parseInt( request.getSession().getAttribute("loginId").
toString());
} catch (Exception e) {
}
if (log!=0)
{
Benutzer b=BenutzerPeer.retrieveByPK(log);
bform.setBenutzerId(Integer.toString(log));
bform.setLogin(b.getLogin());
bform.setName(b.getName());
bform.setPasswort(b.getPasswort());
bform.setPasswort2(b.getPasswort());
bform.setServlet(getServlet());
}
}
request.setAttribute("editbenutzerForm",bform);
return mapping.findForward("proceed");
}
Die wichtigste Methode, die die Action bereitstellt, ist die execute() Methode
(vergleichbar mit der service()-Methode in Servlets). Struts ruft diese
Methode auf, nachdem das Formular-Bean gesetzt und als korrekt
ausgewertet wurde. Somit kann die Action-Klasse davon ausgehen, das das
Formular-bean ihre Daten übergeben hat. Der Action-Klasse werden vier
Parameter übergeben:

ActionMapping – Die ActionMapping-Klasse stellt den Zugriff auf die
Informationen bereit, die in dem Eintrag der struts-config.xml abgelegt
sind, der diese Action-Klasse konfiguriert.

ActionForm form – Dies ist das Formular-Bean. Es wurde die validate()
Methode aufgerufen und es wurden keine Fehler zurückgeliefert. Alle
vom Benutzer eingegebenen Daten stehen über das Formular-Bean zur
Verfügung.

HttpServletRequest request – Dies ist das Standard-JSP- oder Servlet
request-Objekt.

HttpServletResponse response – Dies ist das Standard-JSP- oder Servlet
response-Objekt.
Die execute() Methode muss ein ActionForward-Objekt zurückgeben. Dieses
wird vom Controller verwendet, um festzulegen, welche Seite als Nächstes
angezeigt werden soll. Statt jedoch die Seite direkt zu referenzieren, wird die
übergebene ActionMapping verwendet, um den Verweis über einen
Schlüsselnamen zu finden.
Die Schlüsselnamen werden über die struts-config.xml konfiguriert.
In der execute() Methode erzeugt der Controller jetzt eine neue ModelKomponente, setzt die Werte aus dem Formular-Bean und speichert die
Daten persistent in einer Datenbank.
5.2.
Steuerung der Applikation
Normalerweise gibt Action-Klasse ein ActionForward zurück. Diese wird vom
Controller verwendet, um festzulegen, welche Seite als Nächstes angezeigt
werden soll. Aber die Action weiß nicht, wo diese ist, weil der Controller für
die Weiterleitung verantwortlich ist.
Sie können sogar eine Weiterleitung auf eine andere Action vornehmen,
ohne über eine zwischengeschaltete JSP-Datei zu gehen. Stimmt der Pfad in
der struts-config.xml für die angeforderte Weiterleitung mit dem für Actions
verwendeten URI überein (das normalerweise mit .do endet), gibt Struts die
Steuerung unmittelbar an die Action weiter. Dabei kann man über das
request-Objekt weitere Parameter/ Objekte übergeben. spaket von Struts
mehrere Plug-In-Modelle hinzuzufügen.
struts-config.xml
Die Datei struts-config.xml kann folgenden Elemente enthalten:

Datenbankquellen
(Eingeschränkt funktional, abhängig vom verwendetem Model)

ActionForm-Klassen
Definition aller ActionForm-Beans

Globale Ausnahmen

Globale Weiterleitungen
Definition von globalen ActionForwards

Action Mappings
Referenzierung von Actions, Validierung von ActionForm-Beans sowie
Definition der Rücksprungadresse bei fehlgeschlagener Validierung,
Definition von ActionForwards im Action-Klassencontext (Hash-Mapping
Schlüsselwort ->URI)

Controller-Informationen

Message-Resourcen (I18N)

Plug-Ins
Die Datei struts-config.xml bietet jede Menge Optionen für die Konfiguration
der Applikation. Diese Konfigurationsdatei ist die zentrale Stelle, an der
Aktionen, Formulare und JSP-Seiten zusammengeführt werden. In einer
korrekt entworfenen Struts-Applikation weiß die JSP-Seite nichts über die
Action- und die Form-Klassen, die sie unterstützen. Die Action weiß nicht,
wie eine bestimmte Weiterleitungs-Anforderung tatsächlich in eine URI
umwandelt wird, und die ActionForm-Klasse kann von einer oder mehreren
Action-Klassen oder JSP-Seiten verwendet werden.
6.
ausführliches Beispiel: eBay© für Arme (Menschen,
nicht Körperteile)
6.1.
Anlegen einer neuen Struts-Webapplikation in Tomcat / die Datei
web.xml
•
Ohne easyStruts-Support: Die Datei jakarta-struts-1.1.zip von der StrutsHomepage herunterladen und entpacken. Anschließend im TomcatManager die Webapplikation mit dem Verweis auf das entpackte
Verzeichnis manuell deployen. (Verweise auf andere Anleitungen)
•
Ansonsten bitte externe Anleitungen zur Rate ziehen:
http://www-106.ibm.com/developerworks/opensource/library/osecstruts/?Open&ca=daw-co-news
•
Außerdem empfehlen wir, sich mit Tomcat, Servlets und den Aufbau von
Webapplikationen vertraut zu machen.
Die Datei /WEB-INF/web.xml (der Deployment-Descriptor von ServletApplikationen) hat bei Struts folgenden Aufbau:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/j2ee/dtds/webapp_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>seminarstruts.SpecificActionServlet</servletclass>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
<servlet-name>action</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Zwischen den <servlet>...</servlet>-Tags wird das Servlet 'action' definiert:
dieses ActionServlet wiederum ist bei Struts beigelegt und kann, wie in
diesem Beispiel, überschrieben werden.
Die <servlet-mapping>-Tags definieren ein Pattern-Verweis, damit alle URIs,
die auf .do enden, von dem ActionServlet bearbeitet werden.
6.2.
Die struts-config.xml
Damit das ActionServlet weiß, was es tun soll, liest es nun die '/WEBINF/struts-config.xml' aus (gekürzter Ausschnitt):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD
Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<!-- ========== Data Source Configuration
=============================== -->
<data-sources>
...
</data-sources>
<form-beans>
<form-bean name="loginForm"
type="seminarstruts.form.LoginForm">
<form-property
name="passwort"
type="java.lang.String" />
<form-property
name="name"
type="java.lang.String" />
...
</form-bean>
<global-forwards>
<forward name="noDatabase" path="/form/noDatabase.jsp" />
<forward name="mainpage" path="/index.do" />
<forward name="login" path="/login.do" />
</global-forwards>
<action-mappings>
<action
attribute="editartikelForm"
input="/editartikel.do"
name="editartikelForm"
path="/editartikelSubmit"
scope="request"
type="seminarstruts.action.EditartikelSubmitAction">
<forward name="login" path="/login.do" />
<forward name="success" path="/listartikel.do" />
<forward name="cancel" path="/listartikel.do" />
</action>
...
</action-mappings>
...
<message-resources
parameter="seminarstruts.ApplicationResources" />
<message-resources
key="org.apache.struts.action.MESSAGE_en"
parameter="seminarstruts.ApplicationResources_en" />
</struts-config>
Wird nun die URI '/editartikelSubmit.do' aufgerufen wird, schaut das
ActionServlet nun nach einer Action, dessen Path-property
'/editartikelSubmit' heißt, also ohne '.do'.
In diesem Beispiel ist bei der Action noch ein FormBean namens
'editartikelForm' angegeben (und das Property 'validate' ist standardmäßig
'true'), daher wird das FormBean vor der Action-Ausführung validiert. Schlägt
dies fehl, springt das ActionServlet auf das im Property 'input' angegebenen
URI zurück. (Diese beinhaltet hier eine JSP-Seite, die von einer Action
'vorverarbeitet' wird.
Außerdem wird angegeben, dass das ActionForm-Bean im request-Scope
unter dem Namen 'editartikelForm' gespeichert ist/wird (die ActionForm ist
sowohl über die html-Tags als auch über die bean-Tags erreichbar).
6.3.
View-Beispiel: /form/editartikel.jsp
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
<html>
<head>
<title>
<bean:message key="seminarstruts.locale.bearbeiteArtikel"/>
'<bean:write name="editartikelForm" property="name"/>' <bean:message key="seminarstruts.locale.applicationName"/>
<logic:present name="benutzer">
[<bean:message key="seminarstruts.locale.user"/>:
'<bean:write name="benutzer" property="name"/>']
</logic:present>
</title>
</head>
<body>
<html:form action="/editartikelSubmit">
<html:hidden property="artikelId"/>
<html:errors property="artikelId"/><br>
Name : <html:text property="name"/>
<html:errors property="name"/><br>
Beschreibung : <html:text property="beschreibung"/>
<html:errors property="beschreibung"/><br>
Endedatum : <html:text property="endedatum"/>
<html:errors property="endedatum"/><br>
Endezeit : <html:text property="endezeit"/>
<html:errors property="endezeit"/><br>
Startpreis : <html:text property="startpreis"/>
<html:errors property="startpreis"/><br>
<html:submit/><html:cancel/>
</html:form>
</body>
</html>
<html:form>
7.
Weitere Konzepte in Struts
Im Folgenden existieren noch Konzepte, auf die wir nicht eingegangen sind
und auch nicht zeitlich darauf eingehen können.
8.
•
Alle bean-, html- und logic-Tags
•
Nested-, template- und tiles-Tags
•
DynaForms (Formularverarbeitung ohne Java)
•
EJBs in Struts
•
Struts als Client von WebServices
•
Struts-Applikationen verteilen und testen
•
XML in Struts
Fazit
Struts löst auf den ersten Blick viele Standardaufgaben: es stellt zunächst
eine MVC-Lösung bereit. Zwar unterstellen wir nicht, dass man auch sich in
Struts einarbeiten muß; hat man dies aber bereits einmal gelernt, fällt auch
die Einarbeitung in anderen Struts-Projekten leichter. (Herkömmliche
Servlet-/JSP-Anwendungen sind weniger stark strukturiert.)
Es vereinfacht die Formularverarbeitung mithilfe von ActionForms; eine
erfolgreiche Validierung kann die Bedingung für eine Action darstellen.
Desweiteren wird die JSP-Syntax um viele Taglibs erweitert, die das Arbeiten
mit JSPs erleichtert, da weniger Skriptlets eingesetzt werden müssen. Die
Trennung von Darstellung und Model/Controller wird daher weitergeführt.
Nachteilig ist jedoch die gewisse Einarbeitung, bis man das StrutsFramework beherrscht. Dann jedoch kann man die Vorteile von Struts voll
ausspielen.
9.
Anhang
9.1.
Literatur
(1) Struts –JSP-Applikationen mit Struts, JBoss und Apache Axis
Autoren: James Turner, Kevin Bedell
Verlag: Addison-Wesley
(2) Java Server und Servlets
Autoren: Peter Rossbach, Hendrik Schreiber
Verlag: Addison-Wesley
(3) Handbuch der Java-Programmierung
Autor: Guido Krüger
Verlag: Addison-Wesley
9.2.
Links
(1) Jakarta Struts Homepage
http://jakarta.apache.org/struts/
(2) Torque Persistence Layer
http://db.apache.org/torque/
(3) EasyStruts
http://easystruts.sourceforge.net/