Post on 12-Nov-2018
Struts
Struts
Struts is an application framework, i. e. a reusable semicomplete
application that can be used to produce custom applications.
It is maintained by the Apache Jakarta project and it is freeware.
Technically it is a set of Custom Tags, a core servlet and some utility
classes.
(2009-10-29 � 1.1 )
Struts is based on a servlet that is con�gured from an XML-�le. You use
the same servlet for all applications, you just con�gure it di�erently.
In addition it works with ActionForms, Actions, ActionForward and
ActionMappings. We have a structure like:
Initial page Action servlet
Action
form
Action
JSP
config
Struts
JSP
Figure: Struts components
(2009-10-29 � 1.2 )
An ActionForm is a bean that is used to store data. It has
instancevariables, getters and setters. It is created and populated by the
ActionServlet at request.
An Action is a Java class that implements the functionality of the request
An ActionForward is a location that control can be transferred into.
An ActionMapping describes how Actions and ActionForm are related,
what ActionForwards are used. It also maps them into physical locations.
(2009-10-29 � 1.3 )
When using Struts, the servlet captures all requests of a certain pattern.
The initial request is usually mapped into such a request. Each request is
mapped into an Action using an ActionMapping. When the servlet receives
a request, it looks up the Action, creates and populates the required
ActionForms and transfers control to the proper Action.
When the Action completes it transferres control to an ActionForward, i. e.
a logical location that is mapped into some physical page in the con�g-�le.
(2009-10-29 � 1.4 )
As an example to understand how Struts is setup, handles requests and
produce results we will study a simple login application. It contains an
initial page, a login form and a welcome page.
There are one ActionForm, one Action and a number of ActionForwardsthat are described in ActionMappings.
(2009-10-29 � 1.5 )
Our application is built by the following �les:
WEB-INF dist index.jsp pages
./WEB-INF:
classes struts-bean.tld struts-template.tld *struts-config.xml struts.tld
struts-form.tld *web.xml lib struts-html.tld src struts-logic.tld
/WEB-INF/classes:
app resources
./WEB-INF/classes/app:
*Constants.class *LogonForm.class *LogoffAction.class *UserDirectory.class
*LogonAction.class *UserDirectoryException.class
./WEB-INF/classes/resources:
*application.properties *users.properties
./WEB-INF/lib:
struts-config_1_0.dtd web-app_2_2.dtd struts_1_0_2.jar web-app_2_3.dtd
./WEB-INF/src:
build.xml java
(2009-10-29 � 1.6 )
./WEB-INF/src/java:
app resources
./WEB-INF/src/java/app:
*Constants.java *LogonForm.java *LogoffAction.java *UserDirectory.java
*LogonAction.java *UserDirectoryException.java
./WEB-INF/src/java/resources:
*application.properties *users.properties
./dist:
./pages:
*Logon.jsp *Welcome.jsp *struts-power.gif
We should provide the �les marked with a "*�, the others are part of the
Struts framework.
(2009-10-29 � 1.7 )
As usual we need a web.xml as the central con�guration �le. In a Strutsenvironment it setups servlet mappings, points out the separate Strutscon�guration �le and de�nes the Struts taglibs.
<?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>
(2009-10-29 � 1.8 )
<!-- 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>application</param-name>
<param-value>resources.application</param-value>
</init-param>
<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>
(2009-10-29 � 1.9 )
<!-- 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>
<!-- Struts Tag Library Descriptors -->
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-logic</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
(2009-10-29 � 1.10 )
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>
<!-- ======================================== Form Bean Definitions -->
<form-beans>
<form-bean name="logonForm" type="app.LogonForm"/>
</form-beans>
<!-- =================================== Global Forward Definitions -->
<global-forwards>
<forward name="logoff" path="/Logoff.do"/>
<forward name="logon" path="/Logon.do"/>
<forward name="welcome" path="/Welcome.do"/>
</global-forwards>
(2009-10-29 � 1.12 )
<!-- =================================== Action Mapping Definitions -->
<action-mappings>
<action path="/Welcome" type="org.apache.struts.actions.ForwardAction"
parameter="/pages/Welcome.jsp"/>
<action path="/Logon" type="org.apache.struts.actions.ForwardAction"
parameter="/pages/Logon.jsp"/>
<action path="/LogonSubmit" type="app.LogonAction" name="logonForm"
scope="request" validate="true" input="/pages/Logon.jsp">
<forward name="success" path="/pages/Welcome.jsp"/>
</action>
<action path="/Logoff" type="app.LogoffAction">
<forward name="success" path="/pages/Welcome.jsp"/>
</action>
</action-mappings>
</struts-config>
(2009-10-29 � 1.13 )
We now have de�ned our application, the remaing work is to write the
JSP's, html's and Java classes. In addition some property �les are used.
Application.properties:
welcome.title=Struts Logon Example Application
welcome.heading=Welcome!
welcome.message=To get started on your own application, copy the
struts-blank.war to a new WAR file using the name for
your application. Place it in your container's "webapp"
folder (or equivalent), and let your container auto-deploy
the application. Edit the skeleton configuration files as
needed, reload Struts or restart your container, and you are
on your way! (You can find the application.properties file
with this message in the <B>/WEB-INF/src/java /resources</B> folder.)
errors.footer=</UL><HR>
errors.header=<H3><FONT color="red">Validation Error</FONT>
</H3>You must correct the following error(s) before proceeding:<UL>
error.username.required=<LI>Username is required</LI>
error.password.required=<LI>Password is required</LI>
error.logon.invalid=<LI>Username and password provided not found in user directory.
Password must match exactly, including any lower or upper case characters.</LI>
error.logon.connect=<LI>Could not connect to user directory.</LI>
(2009-10-29 � 1.14 )
and users.properties
TED=Husted
CEDRIC=Dumoulin
GEORGE=Franciscus
DAVID=Winterfeldt
CRAIG=McClanahan
(2009-10-29 � 1.15 )
Now we are ready for the rest, we start with our welcome page,
index.jsp:
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<logic:forward name="welcome"/>
<%--
Redirect default requests to Welcome action.
--%>
(2009-10-29 � 1.16 )
This immediately forwards control using an ActionForward that is mapped
in the con�g �les. Since welcome is mapped into Welcome.do, the request
will end up in the server according to the servlet mapping.
This will activate the Action Welcome that will start the page
pages/Welcome.jsp . So the servlet starts this page.
(2009-10-29 � 1.17 )
It goes like
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<HTML>
<HEAD>
<TITLE>Welcome!</TITLE>
<html:base/>
</HEAD>
<BODY>
<logic:present name="user">
<H3>Welcome <bean:write name="user" property="username"/>!</H3>
</logic:present>
<logic:notPresent scope="session" name="user">
<H3>Welcome World!</H3>
</logic:notPresent>
<html:errors/>
<UL>
<LI><html:link forward="logon">Sign in</html:link></LI>
<logic:present name="user">
<LI><html:link forward="logoff">Sign out</html:link></LI>
</logic:present>
</UL>
<IMG src='struts-power.gif' alt='Powered by Struts'>
</BODY>
</HTML> (2009-10-29 � 1.18 )
<%--If user is logged in, display "Welcome ${username}!"
Else display "Welcome World!" Display link to log in page; maintain session id if needed.
If user is logged in, display a link to the sign-out page.
Note: Only the minimum required html or Struts custom tags are used in this example.
--%>
If I am not logged in I only have one option, to log in. If I am logged in I
can log in once more or log out. To login, the we use an ActionForward
logon. The link tag in the JSP will expand into
http://localhost:8080/logon/Logon.do
that will take us into the servlet with Action Logon, which will start
Logon.jsp.
(2009-10-29 � 1.19 )
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<HTML>
<HEAD>
<TITLE>Sign in, Please!</TITLE>
</HEAD>
<BODY>
<html:errors/>
<html:form action="/LogonSubmit" focus="username">
<TABLE border="0" width="100%">
<TR>
<TH align="right">Username:</TH>
<TD align="left"> <html:text property="username"/></TD>
</TR>
(2009-10-29 � 1.20 )
<TR>
<TH align="right">Password:</TH>
<TD align="left"><html:password property="password"/></TD>
</TR>
<TR>
<TD align="right"><html:submit/></TD>
<TD align="left"><html:reset/></TD>
</TR>
</TABLE>
</html:form>
</BODY>
</HTML>
<%--
Allow user to submit username and password to logon action.
--%>
(2009-10-29 � 1.21 )
This presents a form, when �lled in and submitted, the ActionForward
LogonSubmit . This is mapped into the Action LogonSubmit and requires
an ActionForm that should be created, populated and stored in the request
scope. My input should also be validated before it is used. This is done in
the bean.
It also de�nes an ActionForward success that can be used.
(2009-10-29 � 1.22 )
package app;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
/**
* Form bean for the user profile page.
* This form has the following fields,
* with default values in square brackets:
* <ul>
* <li><b>password</b> - Entered password value
* <li><b>username</b> - Entered username value
* </ul>
*
* @author Ted Husted
*/
(2009-10-29 � 1.23 )
public final class LogonForm extends ActionForm {
// ---------------------------------------Instance Variables
private String password = null;
private String username = null;
// ------------------------------------------ Properties
public String getPassword() {
return (this.password);
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return (this.username);
}
public void setUsername(String username) {
this.username = username;
}
//--------------------------------------- Public Methods
public void reset(ActionMapping mapping, HttpServletRequest request) {
setPassword(null);
setUsername(null);
}
(2009-10-29 � 1.24 )
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if ((username == null) || (username.length() < 1))
errors.add("username", new ActionError("error.username.required"));
if ((password == null) || (password.length() < 1))
errors.add("password",new ActionError("error.password.required"));
return errors;
}
} // End LogonForm
(2009-10-29 � 1.25 )
The validation returns an ActionError (a HashMap). If that is neither null
nor empty, it will be saved by the controller in the reqeuest scope, and
control will be passed to the value of the input tag.
Otherwise we will enter the Action.
(2009-10-29 � 1.26 )
package app;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
/** * Implementation of <strong>Action</strong>
* that validates a user logon.
*
* @author Craig R. McClanahan
* @author Ted Husted
* @version $Revision: 1.1.1.1 $ $Date: 2002/08/15 15:50:55 $
*/
(2009-10-29 � 1.27 )
public final class LogonAction extends Action {
/**
* Validate credentials with business tier.
*
* @param username The username credential
* @param password The password credential
* @returns true if credentials can be validated
* @exception UserDirectoryException if cannot access directory
*/
public boolean isUserLogon(String username, String password)
throws UserDirectoryException {
return (UserDirectory.getInstance().isValidPassword(username,password));
}
(2009-10-29 � 1.28 )
public ActionForward perform(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// Obtain username and password from web tier
String username = ((LogonForm) form).getUsername();
String password = ((LogonForm) form).getPassword();
// Validate credentials with business tier
boolean validated = false;
try {
validated = isUserLogon(username,password);
}
catch (UserDirectoryException ude) {
// couldn't connect to user directory
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.logon.connect"));
saveErrors(request,errors);
// return to input page
return (new ActionForward(mapping.getInput()));
}
(2009-10-29 � 1.29 )
if (!validated) {
// credentials don't match
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.logon.invalid"));
saveErrors(request,errors);
// return to input page
return (new ActionForward(mapping.getInput()));
}
(2009-10-29 � 1.30 )
// Save our logged-in user in the session,
// because we use it again later.
HttpSession session = request.getSession();
session.setAttribute(Constants.USER_KEY, form);
// Log this event, if appropriate
if (servlet.getDebug() >= Constants.DEBUG) {
StringBuffer message = new StringBuffer("LogonAction: User '");
message.append(username);
message.append("' logged on in session ");
message.append(session.getId());
servlet.log(message.toString());
}
// Return success
return (mapping.findForward(Constants.SUCCESS));
}
} // End LogonAction
(2009-10-29 � 1.31 )
Either we return to the input page or return success. The latter will take us
to /pages/Welcome.jsp that we have seen before. Since we are now logged
in, a logout option will also appear.
The last piece of this is the Logo� Action.
(2009-10-29 � 1.32 )
package app;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Vector;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.util.MessageResources;
/**
* Implementation of <strong>Action</strong> that processes a
* user logoff.
*j * @author Craig R. McClanahan
* @author Ted Husted
* @version $Revision: 1.1.1.1 $ $Date: 2002/08/15 15:50:55 $
*/
(2009-10-29 � 1.33 )
public final class LogoffAction extends Action {
public ActionForward perform(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// Extract attributes we will need
HttpSession session = request.getSession();
LogonForm user = (LogonForm) session.getAttribute(Constants.USER_KEY);
// Log this user logoff
if (user != null) {
if (servlet.getDebug() >= Constants.DEBUG) {
StringBuffer message = new StringBuffer("LogoffAction: User '");
message.append(user.getUsername());
message.append("' logged off in session ");
message.append(session.getId());
servlet.log(message.toString());
}
}
else {
if (servlet.getDebug() >= Constants.DEBUG) {
StringBuffer message = new StringBuffer("LogoffAction: User '");
message.append(session.getId());
servlet.log(message.toString());
}
}
(2009-10-29 � 1.34 )
// Remove user login
session.removeAttribute(Constants.USER_KEY);
// Return success
return (mapping.findForward(Constants.SUCCESS));
}
} // end LogoffAction
(2009-10-29 � 1.35 )