Struts ist ein sehr flexibles und leistungsfähiges Open-Source-Framework für Thin-Client-Webanwendungen zur Standardisierung der Verarbeitung von Requests.
Clientseitig werden dabei HTML-Seiten (eventuell ergänzt um CSS und JavaScript) im Webbrowser eingesetzt.
Serverseitig findet Java Verwendung in Form von Servlets, JSP (Java Server Pages) und JavaBeans (eventuell auch EJB und weitere Java-EE-Komponenten).
Vorteile von Struts sind die Vereinfachung und Standardisierung von:
+ Requestverarbeitung
+ Validierung der Benutzereingaben
+ Fehlerbehandlung
+ Internationalisierung und Lokalisierung
+ Trennung der Präsentationsschicht von der Logikschicht
+ Erweiterbarkeit
Im folgenden ersten Teil wird ein einfaches Beispiel mit manueller Validierung vorgestellt (per 'validate()' in 'ActionForm').
Im "zweiten Teil" wird ein Beispiel mit dynamisch erzeugter Daten-JavaBean (DynaBean) und deklarativer Validierung (StrutsValidator) vorgestellt (per 'DynaValidatorForm' und 'validation.xml').
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<display-name>My Struts Application</display-name>
<!-- Standard Action Servlet Configuration (with debugging) -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<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>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- Standard Action Servlet Mapping -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- The Usual Welcome File List -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <logic:redirect forward="startForwardName" />
<%@ 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:html locale="true">
<head>
<title><bean:message key="welcome.title" /></title>
<html:base />
</head>
<body bgcolor="white">
<logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application">
<font color="red">ERROR: Application resources not loaded</font>
</logic:notPresent>
<h3><bean:message key="welcome.heading" /></h3>
<p> <bean:message key="welcome.message" /></p>
<html:form action="/htmlFormActionPath" focus="username">
<p> <bean:message key="welcome.Name" />:
<html:text property="username" size="40" maxlength="40" /><br/>
<font color=red><html:errors property="username" /></font></p>
<p> <bean:message key="welcome.Password" />:
<html:text property="password" size="40" maxlength="40" /><br/>
<font color=red><html:errors property="password" /></font></p>
<p> <html:submit property="action" value="Weiter" />
<html:submit property="action" value="Abbrechen" /></p>
</html:form>
</body>
</html:html>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:html>
<head>
<title>Ergebnisanzeige</title>
</head>
<body>
<h1>Eingegebene Daten</h1>
<p> Name:
<b><bean:write property="username"
name="MeinDatenFormBeanName" /></b></p>
<p> Passwort:
<b><bean:write property="password"
name="MeinDatenFormBeanName" /></b></p>
</body>
</html:html>
package meinpackage;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public final class MeineDatenFormBean extends ActionForm
{
private String username = null;
private String password = null;
private String action = null;
public String getUsername() { return this.username; }
public String getPassword() { return this.password; }
public String getAction() { return this.action; }
public void setUsername( String username ) { this.username = username; }
public void setPassword( String password ) { this.password = password; }
public void setAction( String action ) { this.action = action; }
public void reset( ActionMapping mp, HttpServletRequest rq )
{
username = null;
password = null;
action = null;
}
public ActionErrors validate( ActionMapping mp, HttpServletRequest rq )
{
ActionErrors errors = null;
if( !"Weiter".equals( action ) ) {
username = null;
password = null;
} else {
if( username == null || username.length() < 1 ) {
if( errors == null ) errors = new ActionErrors();
errors.add( "username", new ActionError( "error.username.required" ) );
}
if( password == null || password.length() < 1 ) {
if( errors == null ) errors = new ActionErrors();
errors.add( "password", new ActionError( "error.password.required" ) );
}
}
return errors;
}
}
package meinpackage;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public final class MeineAuswerteAction extends Action
{
public ActionForward execute( ActionMapping mp,
ActionForm fm,
HttpServletRequest rq,
HttpServletResponse rp )
{
MeineDatenFormBean dfb = (MeineDatenFormBean)fm;
String sAction = dfb.getAction();
return mp.findForward( sAction );
}
}
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean
name="MeinDatenFormBeanName"
type="meinpackage.MeineDatenFormBean" />
</form-beans>
<global-forwards>
<forward name="startForwardName" path="/StartActionPath.do" />
</global-forwards>
<action-mappings>
<action
path="/StartActionPath"
forward="/pages/EingabeFormular.jsp" />
<action
path="/htmlFormActionPath"
type="meinpackage.MeineAuswerteAction"
name="MeinDatenFormBeanName"
scope="request"
input="/pages/EingabeFormular.jsp">
<forward name="Weiter" path="/ErgebnisanzeigeActionPath.do" />
<forward name="Abbrechen" path="/StartActionPath.do" />
</action>
<action
path="/ErgebnisanzeigeActionPath"
forward="/pages/ErgebnisAnzeige.jsp" />
</action-mappings>
<message-resources parameter="resources.MessageResources" />
</struts-config>
# -- standard errors --
errors.header=<UL>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</UL>
# -- validator --
errors.invalid={0} is invalid.
errors.maxlength={0} can not be greater than {1} characters.
errors.minlength={0} can not be less than {1} characters.
errors.range={0} is not in the range {1} through {2}.
errors.required={0} is required.
errors.byte={0} must be an byte.
errors.date={0} is not a date.
errors.double={0} must be an double.
errors.float={0} must be an float.
errors.integer={0} must be an integer.
errors.long={0} must be an long.
errors.short={0} must be an short.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
# -- other --
errors.cancel=Operation cancelled.
errors.detail={0}
errors.general=The process did not complete. Details should follow.
errors.token=Request could not be completed. Operation is not in sequence.
# -- welcome --
welcome.title=My Struts Application
welcome.heading=Welcome!
welcome.message=First small Struts Application. Reads some information and displays them.
welcome.Name=Name
welcome.Password=Password
error.username.required=Error: Username required!
error.password.required=Error: Password required!
# -- welcome -- welcome.title=Meine Struts Applikation welcome.heading=Willkommen! welcome.message=Erste kleine Struts-Anwendung. Liest Informationen ein und gibt sie wieder. welcome.Name=Name welcome.Password=Passwort error.username.required=Fehler: Benutzername wird benötigt! error.password.required=Fehler: Passwort wird benötigt!
<project name="blank" basedir="../" default="all">
<!-- Local system paths -->
<property name="servlet.jar" value="/Tools/Tomcat/common/lib/servlet-api.jar" />
<property name="jdbc20ext.jar" value="/Tools/Tomcat/common/lib/jdbc2_0-stdext.jar" />
<!-- NOTE: If "dist" target is used, a local
"projects/lib" directory will be utilized or created -->
<property name="distpath.project" value="/projects/lib" />
<!-- Project settings -->
<property name="project.title" value="Meine Struts Applikation " />
<property name="project.distname" value="mystrutsapp" />
<!-- Path settings -->
<property name="doc.path" value="./doc/api" />
<property name="doc.src" value="./src" />
<!-- classpath -->
<path id="compile.classpath">
<pathelement path="${servlet.jar}" />
<pathelement path="lib/commons-beanutils.jar" />
<pathelement path="lib/commons-digester.jar" />
<pathelement path="lib/struts.jar" />
<pathelement path="classes" />
<pathelement path="${classpath}" />
</path>
<!-- Check timestamp on files -->
<target name="prepare">
<tstamp/>
</target>
<!-- Copy any resource or configuration files -->
<target name="resources">
<copy todir="classes" includeEmptyDirs="no">
<fileset dir="src">
<patternset>
<include name="**/*.conf" />
<include name="**/*.properties" />
<include name="**/*.xml" />
<exclude name="build.xml" />
</patternset>
</fileset>
</copy>
</target>
<!-- Normal build of application -->
<target name="compile" depends="prepare,resources">
<javac srcdir="src" destdir="classes">
<classpath refid="compile.classpath" />
</javac>
</target>
<!-- Remove classes directory for clean build -->
<target name="clean" description="Prepare for clean build">
<delete dir="classes" />
<mkdir dir="classes" />
</target>
<!-- Build Javadoc documentation -->
<target name="javadoc" description="Generate JavaDoc API docs">
<delete dir="./doc/api" />
<mkdir dir="./doc/api" />
<javadoc
sourcepath="./src"
destdir="./doc/api"
classpath="${servlet.jar}:${jdbc20ext.jar}"
packagenames="*"
author="true"
private="true"
version="true"
windowtitle="${project.title} API Documentation"
doctitle="<h1>${project.title} Documentation (Version ${project.version})</h1>"
bottom="Copyright © 2005">
<classpath refid="compile.classpath" />
</javadoc>
</target>
<!-- Build entire project -->
<target name="project" depends="clean,prepare,compile,javadoc" />
<!-- Create binary distribution -->
<target name="dist" description="Create binary distribution">
<mkdir dir="${distpath.project}" />
<jar jarfile="${distpath.project}/${project.distname}.jar"
basedir="./classes" />
<copy file="${distpath.project}/${project.distname}.jar"
todir="${distpath.project}" />
<war basedir="../"
warfile="${distpath.project}/${project.distname}.war"
webxml="web.xml">
<exclude name="${distpath.project}/${project.distname}.war" />
</war>
</target>
<!-- Build project and create distribution-->
<target name="all" depends="project,dist" />
</project>
... siehe zweiter Teil.