Goals After completing this chapter, the student will be able to understand the MVC architecture. set up an application using Struts. use the Struts bean and html tags. process user input from HTML forms through Struts. Prerequisites The student will need to have an understanding of JSP, JavaBeans, and custom tags. Objectives This chapter is presented to provide the student with an understanding of the Struts framework.
"Model-View-Controller" is a way to build applications that promotes complete separation between business logic and presentation. It is not specific to web applications, or Java, or J2EE (it predates all of these by many years), but it can be applied to building J2EE web applications.
The "view" is the user interface, the screens that the end user of the application actually sees and interacts with. In a J2EE web application, views are JSP files. For collecting user input, you will have a JSP that generates an HTML page that contains one or more HTML forms. For displaying output (like a report), you will have a JSP generates an HTML page that probably contains one or more HTML tables. Each of these is a view: a way for the end user to interact with the system, putting data in, and getting data out.
When the user clicks 'Submit' in an HTML form, the request (complete with all the form information) is sent to a "controller". In a J2EE web application, controllers are JavaBeans. The controller's job is to take the data entered by the user (in the HTML form that the JSP generated) and pass it to the "model", which is a separate Java class that contains actual business logic. The model does whatever it does (for instance, store the user's data in a database), then returns some result back to the controller (perhaps a new ID value from the database, or perhaps just a result code saying "OK, I'm done"). The controller takes this value and figures out what the user needs to see next, and presents the user with a new view (for instance, a new JSP file that displays a confirmation that the data they entered was successfully saved).
This all sounds like a lot of work, and it is. But there is a point to architecting applications this way: flexibility. The beauty of model-view-controller separation is that new views and controllers can be created independently of the model. The model -- again, this is pure business logic -- knows nothing of HTML forms or JSP pages. The model defines a set of business functions that only ever get called by controllers, and the controllers act as proxies between the end user (interacting with the view) and the business logic (encapsulated in the model). This means that you can add a new view and its associated controller, and your model doesn't know or care that there are now two different ways for human beings to interact with the application.
For instance, in an application with complicated data entry screens, you could add a JSP that generated a quick-edit form with default values instead of a longer, standard form. Both JSPs (the short form and the long form) could use the same controller; default values could simply be stored in the HTML
Generates html to display any errors that may have occurred during invocation of the
validate() method.
Generates
There is a hidden element here which is invisible. :-)
Generates
.
Generates
.
A link to an external site
Generates an html link.
Generates
for use in collecting information that should not be shown on-screen.
Generates a radio button (
).
Generates
.
Generates tags. Generates a single .
Generates to submit form data entered by the user.
Generates
.
Generates
</tt>.</td> </tr> </tbody></table> <hr /><h3><a name="actionformclass">The <tt>ActionForm</tt> class</a></h3> <p>The purpose of the <tt>ActionForm</tt> class is to contain and provide validation of the user-input data. This class is subclassed for application specific customization.</p> <p>Here is a template for a customized <tt>ActionForm</tt> class with markers denoting where special items should be located in the class with <tt>$</tt> symbols.<br /> </p> <table border="1" cols="1" width="100%"> <tbody><tr> <td><tt>package <b>$PACKAGE_NAME$</b>;</tt> <p><tt>import javax.servlet.http.HttpServletRequest; </tt><br /><tt>import org.apache.struts.action.ActionError; </tt><br /><tt>import org.apache.struts.action.ActionErrors; </tt><br /><tt>import org.apache.struts.action.ActionForm; </tt><br /><tt>import org.apache.struts.action.ActionMapping;</tt></p> <p><tt>import <b>$OTHER_PACKAGES_TO_IMPORT$</b>;</tt></p> <p><tt>public class <b>$THE_NAME_OF_THIS_FORM_CLASS$</b> extends ActionForm {</tt></p> <p><tt> // The attributes of the class should go here</tt><br /><tt> // For example, private int age;</tt><br /><tt> <b>$PRIVATE_ATTRIBUTES_FOR_THIS_CLASS$</b></tt></p> <p><tt> // The constructor method for this class</tt><br /><tt> public <b>$THE_NAME_OF_THIS_FORM_CLASS$</b>() {</tt><br /><tt> }</tt></p> <p><tt> // The method to invoke when a reset occurs</tt><br /><tt> public void reset(ActionMapping mapping, HttpServletRequest request) {</tt><br /><tt> }</tt></p> <p><tt> // The method providing validation of this classes attributes</tt><br /><tt> public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {</tt><br /><tt> ActionErrors errors = new ActionErrors();</tt></p> <p><tt> if (<b>$SOME_CODE_TO_VALIDATE_AN_ATTRIBUTE_OF_THIS_CLASS_RETURNING_true_ON_SUCCESS$</b>) {</tt><br /><tt> // </tt><br /><tt> } else {</tt><br /><tt> // Add an error to the errors to be returned that designates the validation of the</tt><br /><tt> // current attribute failed. The information will come from the Application Resources.</tt><br /><tt> errors.add("<b>$THE_ATTRIBUTES_NAME$</b>", new ActionError("<b>$SOME_KEY_FROM_THE_ApplicationResources.properties_FILE$</b>"));</tt><br /><tt> }</tt></p> <p><tt> // Return the errors</tt><br /><tt> return errors;</tt><br /><tt> }</tt></p> <p><tt> <b>$ACCESSOR_AND_MUTATOR_METHODS_FOR_THE_ATTRIBUTES_OF_THIS_CLASS$</b></tt><br /><tt> // For example,</tt><br /><tt> // public int getAge() { return age; }</tt><br /><tt> // public void setAge(int newAge) { age = newAge; }</tt></p> <p><tt>}</tt></p> </td> </tr> </tbody></table> <hr /><h3><a name="actionclass">The <tt>Action</tt> class</a></h3> <p>The purpose of the <tt>Action</tt> class is to perform the appropriate actions on the user input gathered from the form.</p> <p>Here is a template for a customized <tt>Action</tt> class with markers denoting where special items should be located in the class with <tt>$</tt> symbols.<br /> </p> <table border="1" cols="1" width="100%"> <tbody><tr> <td><tt>package <b>$PACKAGE_NAME$</b>;</tt> <p><tt>import java.util.Vector;</tt><br /><tt>import java.io.IOException; </tt><br /><tt>import java.lang.reflect.InvocationTargetException; </tt><br /><tt>import java.util.Locale; </tt><br /><tt>import java.util.Hashtable;</tt><br /><tt>import javax.servlet.RequestDispatcher; </tt><br /><tt>import javax.servlet.ServletException; </tt><br /><tt>import javax.servlet.http.HttpServletRequest; </tt><br /><tt>import javax.servlet.http.HttpSession; </tt><br /><tt>import javax.servlet.http.HttpServletResponse; </tt><br /><tt>import org.apache.struts.action.Action; </tt><br /><tt>import org.apache.struts.action.ActionError; </tt><br /><tt>import org.apache.struts.action.ActionErrors; </tt><br /><tt>import org.apache.struts.action.ActionForm; </tt><br /><tt>import org.apache.struts.action.ActionForward; </tt><br /><tt>import org.apache.struts.action.ActionMapping; </tt><br /><tt>import org.apache.struts.action.ActionServlet; </tt><br /><tt>import org.apache.struts.util.MessageResources; </tt><br /><tt>import org.apache.struts.util.PropertyUtils;</tt></p> <p><tt>import <b>$OTHER_PACKAGES_TO_IMPORT$</b>;</tt></p> <p><tt>public final class <b>$THE_NAME_OF_THIS_ACTION_CLASS$</b> extends Action {</tt></p> <p><tt> // The constructor method for this class</tt><br /><tt> public <b>$THE_NAME_OF_THIS_ACTION_CLASS$</b>() {</tt><br /><tt> }</tt></p> <p><tt> // The method used for processing the user-input</tt><br /><tt> public ActionForward perform(ActionMapping mapping, </tt><br /><tt> ActionForm form, </tt><br /><tt> HttpServletRequest request, </tt><br /><tt> HttpServletResponse response) </tt><br /><tt> throws IOException, ServletException { </tt></p> <p><tt> Locale locale = getLocale(request); </tt><br /><tt> MessageResources messages = getResources(); </tt><br /><tt> HttpSession session = request.getSession(); </tt><br /><tt> <b>$SOME_FORM_CLASS$</b> <b>$SOME_FORM_CLASS_INSTANCE$</b> = (<b>$SOME_FORM_CLASS$</b>)form;</tt></p> <p><tt> // ActionErrors errors = new ActionErrors();</tt></p> <p><tt> <b>$CODE_FOR_PROCESSING_USER_INPUT$</b></tt></p> <p><tt> if (<b>$PROCESSING_WAS_SUCCESSFUL$</b>) {</tt><br /><tt> } else {</tt><br /><tt> return (mapping.findForward("<b>$FAILURE_FORWARD_PAGE$</b>"));</tt><br /><tt> }</tt></p> <p><tt> if (mapping.getAttribute() != null) {</tt></p> <p><tt> if ("request".equals(mapping.getScope())) </tt><br /><tt> request.removeAttribute(mapping.getAttribute()); </tt><br /><tt> else </tt><br /><tt> session.removeAttribute(mapping.getAttribute());</tt></p> <p><tt> }</tt></p> <p><tt> return (mapping.findForward("<b>$SUCCESS_FORWARD_PAGE$</b>")); </tt></p> <p><tt> }</tt></p> <p><tt>}</tt></p> </td> </tr> </tbody></table> <hr /><h3><a name="simplestruts">SimpleStruts: a simple Struts application</a></h3> <p>(If you have not already done so, you can <a href="http://j2ee.masslight.com/download/j2ee-masslight.zip">download this and other examples</a> used in this course. <a href="http://j2ee.masslight.com/download/j2ee-masslight.tgz">Mac OS X or other UNIX users click here instead</a>.)</p> <p>This example demonstrates the use of Struts for a simple web application using HTML forms. The application will request a name from the user and will display that name on the page containing the form.</p> <p>The <tt>NameForm</tt> class will be used for storing the user input. The <tt>SetNameAction</tt> class will receive an instance of the <tt>NameForm</tt> class containing the user input on which to perform its action. An instance of the <tt>Name</tt> class will be stored in the user's session to represent the name that was last entered.</p> <p><b>Do this:</b></p> <ol><li>Create the directory structure. The root directory is <tt>SimpleStruts</tt>, and it has the standard <tt>WEB-INF</tt> directory with <tt>classes</tt> inside, and <tt>com/masslight/strutsExampleClasses</tt> inside that. It also has a <tt>lib</tt> directory within <tt>WEB-INF</tt>, which is something we haven't seen before; we'll see in a minute what goes there.</li></ol> <div class="dirlisting" id="code_Chapter4_SimpleStruts"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts</b></th> </tr> </thead> <tbody> <tr> <td><pre>SimpleStruts<br /> |<br /> +-- index.jsp (*)<br /> |<br /> +-- build.xml (*)<br /> |<br /> +-- WEB-INF<br /> |<br /> +-- web.xml (*)<br /> |<br /> +-- struts-config.xml (*)<br /> |<br /> +-- struts-bean.tld (*)<br /> |<br /> +-- struts-form.tld (*)<br /> |<br /> +-- struts-html.tld (*)<br /> |<br /> +-- struts-logic.tld (*)<br /> |<br /> +-- struts-template.tld (*)<br /> |<br /> +-- struts.tld (*)<br /> |<br /> +-- app.tld (*)<br /> |<br /> +-- classes<br /> | |<br /> | +-- com<br /> | |<br /> | +-- masslight<br /> | |<br /> | +-- strutsExampleClasses<br /> | |<br /> | +-- ApplicationResources.properties (*)<br /> | |<br /> | +-- Name.java (*)<br /> | |<br /> | +-- NameForm.java (*)<br /> | |<br /> | +-- SetNameAction.java (*)<br /> |<br /> +-- lib<br /> |<br /> +-- struts.jar (*)<br /><br />(*) denotes a file</pre></td> </tr> </tbody> </table><br /></div> <!--<img src="images/imageKPM.JPG" height="458" width="471" /><br />--> <ol start="2"><li>Copy the Struts tag library descriptor files into <tt>WEB-INF</tt>. The files <tt>struts.tld</tt>, <tt>struts-bean.tld</tt>, <tt>struts-form.tld</tt>, <tt>struts-html.tld</tt>, <tt>struts-logic.tld</tt>, and <tt>struts-template.tld</tt> are available in the <tt>lib</tt> directory of your Struts installation.</li></ol> <div class="screen"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <tbody><tr> <td> <pre><code>c:\j2ee\code\Chapter4\SimpleStruts\WEB-INF\> <b>copy c:\j2ee\struts\lib\struts*.tld .</b><br />c:\j2ee\struts\lib\struts-bean.tld<br />c:\j2ee\struts\lib\struts-form.tld<br />c:\j2ee\struts\lib\struts-html.tld<br />c:\j2ee\struts\lib\struts-logic.tld<br />c:\j2ee\struts\lib\struts-template.tld<br />c:\j2ee\struts\lib\struts.tld<br /> 6 file(s) copied.</code><br /></pre> </td> </tr> </tbody></table> </div> <ol start="3"><li>Copy the Struts parser, <tt>struts.jar</tt>, into <tt>WEB-INF/lib/</tt>. This file is available in the <tt>lib</tt> directory of your Struts installation</li><li>Create the tag descriptor library file for any custom tags you may use beyond the Struts tags. In this case, the file defines no custom tags, but it's good practice to have it in place, in case you need to add your own tags later.</li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_app.tld"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/app.tld</b></th> </tr> </thead> <tbody> <tr> <td><pre><code><?xml version="1.0" encoding="ISO-8859-1" ?><br /><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd"><br /><br /><taglib><br /> <tlibversion>1.0</tlibversion><br /> <jspversion>1.1</jspversion><br /> <shortname>utility</shortname><br /> <info><br /> Empty tag library template<br /> </info><br /></taglib></code></pre></td> </tr> </tbody> </table><br /></div> <ol start="5"><li><p>Create the <tt>struts-config.xml</tt> file.</p> <p>There are three main sections to a <tt>struts-config.xml</tt> configuration file. They are the "Form Bean Definitions" section, the "Global Forward Definitions" section, and the "Action Mapping Definitions" section.</p> <p>The <tt>NameForm</tt> class will be defined in the form bean definition section, where it will receive a name for use in the "Action Mapping Definitions" section. The global forward definition section defines a forward called "success".</p> <p>A global forward is defined in the "Global Forward Definitions" section. Whenever this forward is referenced, <tt>index.jsp</tt> will be displayed.</p> <p>The "Action Mapping Definitions" is the most important section within the configuration file. This section takes a form defined in the "Form Bean Definitions" section and maps it to an action class.</p> <p>Here is what the <tt>struts-config.xml</tt> configuration file will look like for this application:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_struts-config.xml"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/struts-config.xml</b></th> </tr> </thead> <tbody> <tr> <td><pre><code><?xml version="1.0" encoding="ISO-8859-1" ?><br /><br /><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd"><br /><br /><struts-config><br /><br /> <!-- ========== Form Bean Definitions =================================== --><br /> <form-beans><br /> <!-- name form bean --><br /> <form-bean name="nameForm" type="com.masslight.strutsExampleClasses.NameForm"><br /> </form-beans><br /><br /> <!-- ========== Global Forward Definitions ============================== --><br /> <global-forwards><br /> <forward name="success" path="/index.jsp"><br /> </global-forwards><br /><br /> <!-- ========== Action Mapping Definitions ============================== --><br /> <action-mappings><br /> <!-- Save user registration --><br /> <action path="/setName" type="com.masslight.strutsExampleClasses.SetNameAction" name="nameForm" scope="request" input="/index.jsp"><br /> </action-mappings><br /><br /></struts-config></code></pre></td> </tr> </tbody> </table><br /></div> <ol start="6"><li><p>Create the <tt>web.xml</tt> file.</p> <p>The <tt>web.xml</tt> web application configuration file will need to define the servlet <tt>ActionServlet</tt>, to which control will be transferred whenever an appropriate URL pattern is accessed. The servlet is defined just as any other servlet will be defined. The URL pattern is specified by a servlet mapping. For this application, the URL pattern is any requested resource that ends with a <tt>.do</tt> extension.</p> <p>In order to use the Struts tags, the <tt>.tld</tt> files describing the tags will need to be included in the configuration file. The references to these tags are made just as they were for our own custom tags in the previous chapter. The Struts framework is simply a complex set of tag libraries (<tt>struts*.tld</tt>), with associated code (<tt>struts.jar</tt>).</p> <p>The <tt>web.xml</tt> configuration file should look like this:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_web.xml"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/web.xml</b></th> </tr> </thead> <tbody> <tr> <td><pre><code><?xml version="1.0" encoding="ISO-8859-1"?><br /><br /><!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"><br /><br /><web-app><br /><br /> <!-- Action Servlet Configuration --><br /> <servlet><br /> <servlet-name>action</servlet-name><br /> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class><br /> <init-param><br /> <param-name>application</param-name><br /> <param-value>com.masslight.strutsExampleClasses.ApplicationResources</param-value><br /> </init-param><br /> <init-param><br /> <param-name>config</param-name><br /> <param-value>/WEB-INF/struts-config.xml</param-value><br /> </init-param><br /> <init-param><br /> <param-name>debug</param-name><br /> <param-value>2</param-value><br /> </init-param><br /> <init-param><br /> <param-name>detail</param-name><br /> <param-value>2</param-value><br /> </init-param><br /> <init-param><br /> <param-name>validate</param-name><br /> <param-value>true</param-value><br /> </init-param><br /> <load-on-startup>2</load-on-startup><br /> </servlet><br /><br /> <!-- Action Servlet Mapping --><br /> <servlet-mapping><br /> <servlet-name>action</servlet-name><br /> <url-pattern>*.do</url-pattern><br /> </servlet-mapping><br /><br /> <!-- The Welcome File List --><br /> <welcome-file-list><br /> <welcome-file>index.jsp</welcome-file><br /> </welcome-file-list><br /><br /> <!-- Application Tag Library Descriptor --><br /> <taglib><br /> <taglib-uri>/WEB-INF/app.tld</taglib-uri><br /> <taglib-location>/WEB-INF/app.tld</taglib-location><br /> </taglib><br /><br /> <!-- Struts Tag Library Descriptors --><br /> <taglib><br /> <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri><br /> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location><br /> </taglib><br /><br /> <taglib><br /> <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri><br /> <taglib-location>/WEB-INF/struts-html.tld</taglib-location><br /> </taglib><br /><br /> <taglib><br /> <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri><br /> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location><br /> </taglib><br /><br /></web-app></code></pre></td> </tr> </tbody> </table><br /></div> <ol start="7"><li><p>The <tt>ApplicationResources.properties</tt> file provides resources that will be used by any subclassed Struts classes (for example, <tt>SetNameAction</tt>). This resources file provides a place to define prompts, labels that will display on buttons, and other information that may change. By placing this information in the <tt>ApplicationResources.properties</tt> file, recompiling any servlets used in the application can be avoided, as well as encouraging separation of logic and presentation.</p> <p>The <tt>ApplicationResources.properties</tt> file looks like this:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_classes_com_masslight_strutsExampleClasses_ApplicationResources.properties"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/classes/com/masslight/strutsExampleClasses/ApplicationResources.properties</b></th> </tr> </thead> <tbody> <tr> <td><pre><code>button.save=Change name<br />button.reset=Reset<br />error.name.required=To change the name, a name must be entered<br />prompt.name=Enter name:<br />welcome.title=A Simple Application</code></pre></td> </tr> </tbody> </table><br /></div> <ol start="8"><li><p>Instances of the <tt>Name</tt> class are placed in the user sessions. Only one will exist in any particular user session. It provides methods for accessing and mutating a name.</p> <p>Place the following inside the <tt>Name.java</tt> file:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_classes_com_masslight_strutsExampleClasses_Name.java"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/classes/com/masslight/strutsExampleClasses/Name.java</b></th> </tr> </thead> <tbody> <tr> <td><pre><code>package com.masslight.strutsExampleClasses;<br /><br />import java.io.Serializable;<br /><br />public final class Name implements Serializable {<br /><br /> private String name = null;<br /><br /> public String getName() {<br /> return (this.name);<br /> }<br /><br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /><br /> public String toString() {<br /> StringBuffer sb = new StringBuffer("Name[name=");<br /> sb.append(name);<br /> sb.append("]");<br /> return (sb.toString());<br /> }<br /><br />}</code></pre></td> </tr> </tbody> </table><br /></div> <ol start="9"><li><p>The <tt>NameForm</tt> class stores and validates the user input. It provides methods for accessing and mutating the data in the form. Notice how the validate method uses information from the <tt>ApplicationResources.properties</tt> file.</p> <p>Place the following in the <tt>NameForm.java</tt> file:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_classes_com_masslight_strutsExampleClasses_NameForm.java"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/classes/com/masslight/strutsExampleClasses/NameForm.java</b></th> </tr> </thead> <tbody> <tr> <td><pre><code>package com.masslight.strutsExampleClasses;<br /><br />import javax.servlet.http.HttpServletRequest;<br />import org.apache.struts.action.ActionError;<br />import org.apache.struts.action.ActionErrors;<br />import org.apache.struts.action.ActionForm;<br />import org.apache.struts.action.ActionMapping;<br /><br />public final class NameForm extends ActionForm {<br /><br /> private String action = "Set";<br /> private String name = null;<br /><br /> public String getAction() {<br /> return (this.action);<br /> }<br /><br /> public void setAction(String action) {<br /> this.action = action;<br /> }<br /><br /> public String getName() {<br /> return (this.name);<br /> }<br /><br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /><br /> public void reset(ActionMapping mapping, HttpServletRequest request) {<br /> this.action = "Set";<br /> this.name = null;<br /> }<br /><br /> public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {<br /> ActionErrors errors = new ActionErrors();<br /> if ((name == null) || (name.length() <></pre></td> </tr> </tbody> </table><br /></div> <ol start="10"><li><p>The <tt>SetNameAction</tt> class has a <tt>perform</tt> method, which receives an instance of the <tt>NameForm</tt> class containing the user input.</p> <p>Although the <tt>perform</tt> method here operates directly on the form data, in a real-world application it should instead delegate this duty to a business logic object. (We will see how this works in chapter 7, once we learn about EJBs.) The <tt>perform</tt> method takes the name from the form and creates a new instance of the <tt>Name</tt> class, which is placed inside the session. If a bean by that name is already present in the session, it is replaced by the new instance.</p> <p>Notice how the class uses this code:</p> <pre><code> return (mapping.findForward("success"));</code></pre> <p>to display the next JSP. A new forward could have been defined in the <tt>struts-config.xml</tt> called "failed" or "DEFCON1". If any of the code in the <tt>perform</tt> method had failed, the user could be forwarded to the JSP page defined in the forward definition.</p> <p>Place the following code in the <tt>SetNameAction.java</tt> file:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_WEB-INF_classes_com_masslight_strutsExampleClasses_SetNameAction.java"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/WEB-INF/classes/com/masslight/strutsExampleClasses/SetNameAction.java</b></th> </tr> </thead> <tbody> <tr> <td><pre><code>package com.masslight.strutsExampleClasses;<br /><br />import java.io.IOException;<br />import java.lang.reflect.InvocationTargetException;<br />import java.util.Locale;<br />import java.util.Hashtable;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br />import org.apache.struts.action.*;<br />import org.apache.struts.util.*;<br /><br />public final class SetNameAction extends Action {<br /><br /> public ActionForward perform(ActionMapping mapping,<br /> ActionForm form,<br /> HttpServletRequest request,<br /> HttpServletResponse response)<br /> throws IOException, ServletException {<br /><br /> Locale locale = getLocale(request);<br /> MessageResources messages = getResources();<br /> HttpSession session = request.getSession();<br /> NameForm nameform = (NameForm)form;<br /> String action = request.getParameter("action");<br /><br /> if (action == null)<br /> action = "Set";<br /><br /> if (servlet.getDebug() >= 1)<br /> servlet.log("SetNameAction: Processing " + action + " action");<br /><br /> Name name = (Name)session.getAttribute("name");<br /><br /> ActionErrors errors = new ActionErrors();<br /><br /> String value = null;<br /><br /> value = nameform.getName();<br /><br /> if ("Set".equals(action)) {<br /> name = null;<br /> name = new Name();<br /> name.setName(nameform.getName());<br /> }<br /><br /> session.setAttribute("name", name);<br /><br /> if (mapping.getAttribute() != null) {<br /><br /> if ("request".equals(mapping.getScope()))<br /> request.removeAttribute(mapping.getAttribute());<br /> else<br /> session.removeAttribute(mapping.getAttribute());<br /><br /> }<br /><br /> return (mapping.findForward("success"));<br /><br /> }<br /><br />}</code></pre></td> </tr> </tbody> </table><br /></div> <ol start="12"><li><p>The view of the application is done with the JSP <tt>index.jsp</tt>. It represents the user interface and allows the user to interact with the application.</p> <p>Information from the <tt>ApplicationResources.properties</tt> file is used for the page title, prompts, and the <tt>Submit</tt> button label. This is done with the <tt><bean:message></tt> tag. The attribute <tt>"key"</tt> is used to specify the application resource to lookup in the <tt>ApplicationResources.properties</tt> file.</p> <p>Any errors that were found by the <tt>validate</tt> method of the <tt>NameForm</tt> class are displayed by using the <tt><html:errors/></tt> tag.</p> <p>The <tt>action</tt> attribute of the <tt><form></tt> tag is <tt>"setName"</tt>. When the user clicks the <tt>Submit</tt> button, the action defined for <tt>setName</tt> in <tt>struts-config.xml</tt> is invoked.</p> <p>A text field is created and associated with the property "name" in an instance of the <tt>NameForm</tt> class by using the attribute property in the <tt><html:text></tt> tag. Two optional attributes are used to define the length and the maximum characters to accept.</p> <p>A new tag is introduced from the Struts logic tag library. <tt><logic:present></tt> checks to see if a bean whose name is specified with the name attribute exists. If a user has previously entered a name and submitted it without any errors, then a bean by that name will exist. Whenever the bean is found, the information in the enclosed by the <tt><logic:present></tt> tags are included in the html that is generated. Don't worry about this for now; the next chapter will discuss handling conditional logic in Struts.</p> <p>The <tt><bean:write></tt> tag is used to display the value of the property in the bean specified by the "property" and "name" attributes.</p> <p>Place the following inside the <tt>index.jsp</tt> file:</p> </li></ol> <div class="filelisting" id="code_Chapter4_SimpleStruts_index.jsp"> <table border="1" cellpadding="10" cellspacing="0" width="100%"> <thead> <tr> <th><b>code/Chapter4/SimpleStruts/index.jsp</b></th> </tr> </thead> <tbody> <tr> <td><pre><code><%@ page language="java" %><br /><%@ taglib uri="/WEB-INF/app.tld" prefix="app" %><br /><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><br /><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><br /><%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><br /><br /><html:html><br /> <head><br /> <title><br /> <bean:message key="welcome.title"><br /> </title><br /> <html:base/><br /> </head><br /> <body><br /> <html:errors/><br /> <html:form action="/setName"><br /> <html:hidden property="action"><br /> <bean:message key="prompt.name"><br /> <html:text property="name" size="16" maxlength="16"><br /> <br /></br><br /> <html:submit><br /> <bean:message key="button.save"><br /> </html:submit><br /> <html:reset><br /> <bean:message key="button.reset"><br /> </html:reset><br /> </html:form><br /> <hr /></hr><br /> <logic:present name="name"><br /> <span style="color:blue;"><br /> <bean:write name="name" property="name"><br /> </span><br /> <hr /></hr><br /> </logic:present><br /> </body><br /></html:html></code></pre></td> </tr> </tbody> </table><br /></div> <ol start="13"><li><tt>ant all</tt> to compile, jar, and deploy.</li><li>Go to <tt>http://localhost:8080/SimpleStruts/index.jsp</tt> to test your application</li></ol> <p><img src="http://j2ee.masslight.com/images/image0F0.JPG" width="485" height="316" /></p> <p><img src="http://j2ee.masslight.com/images/image4F4.JPG" width="485" height="316" /></p> <p><img src="http://j2ee.masslight.com/images/imageULT.JPG" width="485" height="316" /></p> <div class="exercises"> <hr /><h3><a name="exercises">Exercises</a></h3> <h4>Exercise 1. Extending our form</h4> <p>Add the following to the form and appropriate methods and variables to the Name, SetNameAction, and NameForm classes to process the information correctly:</p> <ul><li>a set of radio buttons for selection of contentness (happy or sad)</li><li>a set of checkboxes to allow the user to select favorite types of music (rock, gospel, folk, country, and classical)</li><li>a selection to choose an age range (18-24, 25-40, 41-67, 67-300)</li><li>a text-area for entering side notes about the person (5 rows and 40 columns)</li></ul> <h4>Exercise 2. Think</h4> <p>What happens when the browser is closed and the site is visited once again? How can this be avoided?</p> </div> <!-- begin standard footer --> <div class="footer"> <hr /> <h6>Copyright © 2001-2 <a href="http://www.masslight.com/">MassLight, Inc.</a></h6> <div class="license"> <p>MassLight, Inc. specializes in professional developer training. The full version of this course includes 20 hours of lecture, 20 hours of hands-on development labs, and additional printed materials to supplement the material you see here. If you are interested in having us teach this course at your company, please <a href="http://www.masslight.com/Profile.html">contact us</a> for details.</p> <p>Permission is granted to copy, distribute, and/or modify this material under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in <a href="http://j2ee.masslight.com/license.html">GNU Free Documentation License</a>.</p> <p>The code samples in this course are distributed under the BSD license. See the individual code files for details.</p> </div> </div> <!-- end standard footer --> <!-- $Revision: 1.13 $ $Date: 2002/04/09 19:25:40 $ -->
Không có nhận xét nào:
Đăng nhận xét