现在的位置: 首页 > 综合 > 正文

struts入门(1)

2012年04月30日 ⁄ 综合 ⁄ 共 33434字 ⁄ 字号 评论关闭

 本章讲解了一个简单的Struts应用例子helloapp应用,这个例子可以帮助读者迅速入门,获得开发Struts应用的基本经验。该应用的功能非常简单,接受用户输入的姓名<name>,然后输出“Hello <name>”。开发helloapp应用涉及以下内容:

l         分析应用需求

l         把基于MVC设计模式的Struts框架运用到应用中

l         创建视图组件,包括HTML表单(hello.jsp)和ActionForm Bean(HelloForm.java)

l         创建application.properties资源文件

l         数据验证,包括表单验证和业务逻辑验证

l         创建控制器组件: HelloAction.java

l         创建模型组件: PersonBean.java

l         创建包含被各个模块共享的常量数据的Java文件: Constants.java

l         创建配置文件:web.xml和struts-config.xml

l         编译、发布和运行helloapp应用

2.1  分析helloapp应用的需求
在开发应用时,首先从分析需求入手,列举该应用的各种功能,以及限制条件。helloapp应用的需求非常简单,包括如下需求:

l         接受用户输入的姓名<name>,然后返回字符串“Hello <name> !”

l         如果用户没有输入姓名就提交表单,将返回出错信息,提示用户首先输入姓名。

l         如果用户输入姓名为“Monster”,将返回出错信息,拒绝向“Monster”打招呼。

l         为了演示模型组件的功能,本应用使用模型组件来保存用户输入的姓名。

2.2  运用Struts框架
下面把Struts框架运用到helloapp应用中。Struts框架可以方便迅速的把一个复杂的应用划分成模型、视图和控制器组件,而Struts的配置文件struts-config.xml则可以灵活的组装这些组件,简化开发过程。

以下是helloapp应用的各个模块的构成:

l         模型包括一个JavaBean组件PersonBean,它有一个userName属性,代表用户输入的名字。它提供了get/set方法,分别用于读取和设置userName属性,它还提供一个save()方法,负责把userName属性保存到持久化存储系统中,如数据库或文件系统。对于更为复杂的Web应用,JavaBean组件可以作为EJB或Web服务的前端组件。

l         视图包括一个JSP文件hello.jsp,它提供用户界面,接受用户输入的姓名。视图还包括一个ActionForm Bean,它用来存放表单数据,并进行表单验证,如果用户没有输入姓名就提交表单,将返回出错信息。

l         控制器包括一个Action类HelloAction,它完成三项任务:1.进行业务逻辑验证,如果用户输入的姓名为“Monster”, 将返回错误消息;2.调用模型组件PersonBean的save()方法,保存用户输入的名字;3.决定将合适的视图组件返回给用户。

 

除了创建模型、视图和控制器组件,还需要创建Struts的配置文件struts-config.xml,它可以把这些组件组装起来,使它们协调工作。此外,还需要创建整个Web应用的配置文件web.xml。

2.3  创建视图组件
本例中,视图包括两个组件:

l         一个JSP文件:hello.jsp

l         一个ActionForm Bean: HelloForm Bean

 

下面分别讲述如何创建这两个组件。

2.3.1  创建JSP文件
hello.jsp提供用户界面,能够接受用户输入的姓名。此外,本Web应用的所有输出结果也都由hello.jsp显示给用户。图2-1显示了hello.jsp提供的网页。

图2-1  hello.jsp的网页

在图2-1中,用户输入姓名“Weiqin”后,按提交表单,本应用将返回“Hello Weiqin!”,参见图2-2。

图2-2  hello.jsp接受用户输入后正常返回的网页

 

例程2-1为hello.jsp文件的源代码。

例程2-1  hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ 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="hello.jsp.title"/></title>

    <html:base/>

  </head>

 

  <body bgcolor="white"><p>

    <h2><bean:message key="hello.jsp.page.heading"/></h2><p>

   <html:errors/><p>                    

 

    <logic:present name="personbean" scope="request">

       <h2>

         <bean:message key="hello.jsp.page.hello"/>

         <bean:write name="personbean" property="userName" />!<p>

       </h2>

    </logic:present>

 

    <html:form action="/HelloWorld.do" focus="userName" >

      <bean:message key="hello.jsp.prompt.person"/>

      <html:text property="userName" size="16" maxlength="16"/><br>

      <html:submit property="submit" value="Submit"/>

      <html:reset/>

 

    </html:form><br>

 

    <html:img page="/struts-power.gif" alt="Powered by Struts"/>

  </body>

</html:html>

以上基于Struts框架的JSP文件有以下特点:

l         没有任何Java程序代码

l         使用了许多Struts的客户化标签,例如<html:form>和<logic:present>标签

l         没有直接提供文本内容,取而代之的是<bean:message>标签,输出到网页上的文本内容都是由<bean:message>标签来生成的。例如:

<bean:message key="hello.jsp.prompt.person"/>

 

Struts客户化标签是联系视图组件和Struts框架中其它组件的纽带。这些标签可以访问或显示来自于控制器和模型组件的数据。在本书第12章至16章讲专门介绍Struts标签的用法,本节先简单介绍几种重要的Struts标签。

 

hello.jsp开头几行用于声明和加载Struts标签库:

<%@ 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文件使用了Struts Bean、Html和Logic 标签库,这是加载客户化标签库的标准JSP语法。

hello.jsp中使用了来自 Struts HTML标签库中的标签,包括<html:errors>, <html:form>和<html:text>:

l         <html:errors>:用于显示Struts框架中其他组件产生的错误消息。

l         <html:form>:用于创建HTML表单,它能够把HTML表单的字段和ActionForm Bean的属性关联起来。

l         <html:text>:该标签是<html:form>的子标签,用于创建HTML表单的文本框。它和ActionForm Bean的属性相关联。

 

hello.jsp中使用了来自Struts Bean标签库的两个标签<bean:message>和<bean:write> :

l         <bean:message>:用于输出本地化的文本内容,它的key属性指定消息key,和消息key匹配的文本内容来自于专门的Resource Bundle,关于Resource Bundle的概念参见本书第9章(Struts应用的国际化)。

l         <bean:write>:用于输出JavaBean的属性值。本例中,它用于输出personbean对象的userName属性值:

<bean:write name="personbean" property="userName" />

 

hello.jsp使用了来自Struts Logic标签库的<logic:present>标签。<logic:present>标签用来判断JavaBean在特定的范围内是否存在,只有当JavaBean存在,才会执行标签主体中的内容:

<logic:present name="personbean" scope="request">

       <h2>

         Hello <bean:write name="personbean" property="userName" />!<p>

       </h2>

</logic:present>

本例中,<logic:present>标签用来判断在request范围内是否存在personbean对象,如果存在,就输出personbean的userName属性值。和<logic:present>标签相对的是<logic:notPresent>标签,它表示只有当JavaBean在特定的范围内不存在,才会执行标签主体中的内容。

2.3.2  创建消息资源文件
hello.jsp使用<bean:message>标签来输出文本内容。这些文本来自于Resource Bundle,每个Resource Bundle都对应一个或多个本地化的消息资源文件,本例中的资源文件为application.properties,例程2-2是该消息资源文件的内容。

例程  2-2 application.properties文件

#Application Resources for the "Hello" sample application

hello.jsp.title=Hello - A first Struts program

hello.jsp.page.heading=Hello World! A first Struts application

hello.jsp.prompt.person=Please enter a UserName to say hello to :

hello.jsp.page.hello=Hello

 

#Validation and error messages for HelloForm.java and HelloAction.java

hello.dont.talk.to.monster=We don't want to say hello to Monster!!!

hello.no.username.error=Please enter a <i>UserName</i> to say hello to!

以上文件以“消息key/消息文本”的格式存放数据,文件中“#”后面为注释行。对于以下JSP代码:

<bean:message key="hello.jsp.title"/>

<bean:message>标签的key属性为“hello.jsp.tilte”,在Resource Bundle中与之匹配的内容为:

hello.jsp.title=Hello - A first Struts program

因此,以上<bean:message>标签将把“Hello - A first Struts program”输出到网页上。

2.3.3  创建ActionForm Bean
当用户提交了HTML表单,Struts框架自动把表单数据组装到ActionForm Bean中。ActionForm Bean中的属性和HTML表单中的字段一一对应。ActionForm Bean还提供数据验证方法,以及把属性重新设置为默认值的方法。Struts框架中定义的ActionForm类是抽象的,必须在应用中创建它的子类,来存放具体的HTML表单数据。例程2-3为HelloForm.java的源程序, 它用于处理hello.jsp中的表单数据。

例程2-3  HelloForm.java

package hello;

 

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionMessage;

import org.apache.struts.action.ActionErrors;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionMapping;

 

public final class HelloForm extends ActionForm {

 

    private String userName = null;

 

    public String getUserName() {

        return (this.userName);

    }

 

    public void setUserName(String userName) {

        this.userName = userName;

    }

  

    /**

     * Reset all properties to their default values.

     */

    public void reset(ActionMapping mapping, HttpServletRequest request) {

        this.userName = null;

    }

 

    /**

     * Validate the properties posted in this request. If validation errors are

     * found, return an <code>ActionErrors</code> object containing the errors.

     * If no validation errors occur, return <code>null</code> or an empty

     * <code>ActionErrors</code> object.

     */

    public ActionErrors validate(ActionMapping mapping,

                                 HttpServletRequest request) {

 

        ActionErrors errors = new ActionErrors();

 

        if ((userName == null) || (userName.length() < 1))

            errors.add("username", new ActionMessage("hello.no.username.error"));

 

        return errors;

    }

}

从以上代码可以看出,ActionForm Bean实质上是一种JavaBean,不过它除了具有JavaBean的常规方法,还有两个特殊方法:

l         validate():用于表单验证。

l         reset():把属性重新设置为默认值。

2.3.4  数据验证
几乎所有和用户交互的应用都需要数据验证,而从头设计并开发完善的数据验证机制往往很费时。幸运的是,Struts框架提供了现成的、易于使用的数据验证功能。Struts框架的数据验证可分为两种类型:表单验证和业务逻辑验证,在本例中,它们分别运用于以下场合:

l         表单验证:如果用户没有在表单中输入姓名,就提交表单,将生成表单验证错误

l         业务逻辑验证:如果用户在表单中输入的姓名为“Monster”,按照本应用的业务规则,不允许向“Monster”打招呼,因此将生成业务逻辑错误。

 

第一种类型的验证,即表单验证由ActionForm Bean来负责处理。在本例中,HelloForm.java的validate()方法负责完成这一任务:

public ActionErrors validate(ActionMapping mapping,

                                 HttpServletRequest request) {

        ActionErrors errors = new ActionErrors();

 

        if ((userName == null) || (userName.length() < 1))

            errors.add("username", new ActionMessage("hello.no.username.error"));

 

        return errors;

    }

}

当用户提交了HTML表单,Struts框架自动把表单数据组装到ActionForm Bean中。接下来Struts框架会自动调用ActionForm Bean的validate()方法进行表单验证。如果validate()方法返回的ActionErrors 对象为null,或者不包含任何ActionMessage对象,就表示没有错误,数据验证通过。如果ActionErrors中包含ActionMessage对象,就表示发生了验证错误,Struts框架会把ActionErrors对象保存到request范围内,然后把请求转发到恰当的视图组件,视图组件通过<html:errors>标签把request范围内的ActionErrors对象中包含的错误消息显示出来,提示用户修改错误。

 

在Struts早期的版本中,使用ActionError类来表示错误消息,ActionError类是ActionMessage的子类。Struts1.2将废弃ActionError,统一采用ActionMessage类来表示正常或错误消息。

第二种类型的验证,即业务逻辑验证,由Action来负责处理,参见本章2.4.3节。

2.4  创建控制器组件
控制器组件包括ActionServlet类和Action类。ActionServlet类是Struts框架自带的,它是整个Struts框架的控制枢纽,通常不需要扩展。Struts框架提供了可供扩展的Action类,它用来处理特定的HTTP请求,例程2-4为HelloAction类的源程序。

例程2-4  HelloAction.java

package hello;

 

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.ActionMessage;

import org.apache.struts.action.ActionMessages;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.util.MessageResources;

 

public final class HelloAction extends Action {

 

    /**

     * Process the specified HTTP request, and create the corresponding HTTP

     * response (or forward to another web component that will create it).

     * Return an <code>ActionForward</code> instance describing where and how

     * control should be forwarded, or <code>null</code> if the response has

     * already been completed.

     */

    public ActionForward execute(ActionMapping mapping,

                                 ActionForm form,

                                 HttpServletRequest request,

                                 HttpServletResponse response)

    throws Exception {

 

        // These "messages" come from the ApplicationResources.properties file

        MessageResources messages = getResources(request);

 

        /*

         * Validate the request parameters specified by the user

         * Note: Basic field validation done in HelloForm.java

         *       Business logic validation done in HelloAction.java

         */

        ActionMessages errors = new ActionMessages();

        String userName = (String)((HelloForm) form).getUserName();

 

        String badUserName = "Monster";

 

        if (userName.equalsIgnoreCase(badUserName)) {

           errors.add("username", new ActionMessage("hello.dont.talk.to.monster",

badUserName ));

           saveErrors(request, errors);

           return (new ActionForward(mapping.getInput()));

        }

 

        /*

         * Having received and validated the data submitted

         * from the View, we now update the model

         */

        PersonBean pb = new PersonBean();

        pb.setUserName(userName);

        pb.saveToPersistentStore();

 

        /*

         * If there was a choice of View components that depended on the model

         * (or some other) status, we'd make the decision here as to which

         * to display. In this case, there is only one View component.

         *

         * We pass data to the View components by setting them as attributes

         * in the page, request, session or servlet context. In this case, the

         * most appropriate scoping is the "request" context since the data

         * will not be neaded after the View is generated.

         *

         * Constants.PERSON_KEY provides a key accessible by both the

         * Controller component (i.e. this class) and the View component

         * (i.e. the jsp file we forward to).

         */

 

        request.setAttribute( Constants.PERSON_KEY, pb);

 

        // Remove the Form Bean - don't need to carry values forward

        request.removeAttribute(mapping.getAttribute());

 

        // Forward control to the specified success URI

        return (mapping.findForward("SayHello"));

    }

}

 

HelloAction.java是本应用中最复杂的程序,下面分步讲解它的工作机制和流程。

2.4.1  Action类的工作机制
所有的Action类都是org.apache.struts.action.Action的子类。Action子类应该覆盖父类的execute() 方法。当ActionForm Bean被创建,并且表单验证顺利通过后, Struts框架就会调用Action类的execute()方法。execute()方法的定义如下:

 

public ActionForward execute(ActionMapping mapping,

                  ActionForm form,

                  HttpServletRequest request,

                  HttpServletResponse response) throws IOException, ServletException ;

 

execute()方法包含以下参数:

l         ActionMapping:包含了这个Action的配置信息,和struts-config.xml文件中的<action>元素对应。

l         ActionForm:包含了用户的表单数据,当Struts框架调用execute()方法时,ActionForm中的数据已经通过了表单验证。

l         HttpServletRequest:当前的HTTP请求对象

l         HttpServletResponse:当前的HTTP响应对象

 

Action类的execute()方法返回ActionForward对象,它包含了请求转发路径信息。

2.4.2  访问封装在MessageResources中的本地化文本
在本例中,Action类的execute()方法首先获得MessageResources对象:

MessageResources messages = getResources(request);

 

在Action类中定义了getResources(HttpServletRequest request)方法,该方法返回当前默认的MessageResources对象,它封装了Resource Bundle中的文本内容。接下来Action类就可以通过MessageResources对象来访问文本内容。例如,如果要读取消息key为“hello.jsp.title”对应的文本内容,可以调用MessageResources类的getMessage(String key)方法:

String title=messages.getMessage("hello.jsp.title");

2.4.3  业务逻辑验证
接下来,Action类的execute()方法执行业务逻辑验证:

ActionMessages errors = new ActionMessages();

String userName = (String)((HelloForm) form).getUserName();

 

String badUserName = "Monster";

 

if (userName.equalsIgnoreCase(badUserName)) {

   errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName ));

   saveErrors(request, errors);

   return (new ActionForward(mapping.getInput()));

}

如果用户输入的姓名为“Monster”,将创建包含错误信息的ActionMessage对象,ActionMessage对象被保存到ActionMessages对象中。接下来调用在Action基类中定义的saveErrors()方法,它负责把ActionMessages对象保存到request范围内。最后返回ActionForward对象,Struts框架会根据ActionForward对象包含的转发信息把请求转发到恰当的视图组件,视图组件通过<html:errors>标签把request范围内的ActionMessages对象中包含的错误消息显示出来,提示用户修改错误。

在2.3.4节还提到了ActionErrors对象,图2-3显示了ActionMessages、ActionErrors、ActionMessage和ActionError类的类框图。ActionErrors继承ActionMessages,ActionError继承ActionMessage,ActionMessages和ActionMessage之间为聚集关系,即一个ActionMessages对象中可以包含多个ActionMessage对象。

 

图2-3  ActionMessages、ActionErrors、ActionMessage和ActionError类的类框图

表单验证通常只对用户输入的数据进行简单的语法和格式检查,而业务逻辑验证会对数据进行更为复杂的验证,很多情况下,需要模型组件的介入,才能完成业务逻辑验证。

2.4.4  访问模型组件
接下来,HelloAction类创建了一个模型组件PersonBean对象,并调用它的saveTopersistentStore()方法来保存userName属性:

PersonBean pb = new PersonBean();

pb.setUserName(userName);

pb.saveToPersistentStore();

本例仅提供了Action类访问模型组件简单的例子。在实际应用中,Action类会访问模型组件,完成更加复杂的功能,例如:

l         从模型组件中读取数据,用于被视图组件显示

l         和多个模型组件交互

l         依据从模型组件中获得的信息,来决定返回哪个视图组件

2.4.5  向视图组件传递数据
Action类把数据存放在request或session范围内,以便向视图组件传递信息。以下是 HelloAction.java向视图组件传递数据的代码:

request.setAttribute( Constants.PERSON_KEY, pb);

 

// Remove the Form Bean - don't need to carry values forward

request.removeAttribute(mapping.getAttribute());

 

以上代码完成两件事:

l         把PersonBean对象保存在request范围内。

l         从request范围内删除ActionForm Bean。由于后续的请求转发目标组件不再需要HelloForm Bean,所以可将它删除。

 

2.4.6  把HTTP请求转发给合适的视图组件
最后,Action类把流程转发给合适的视图组件。

// Forward control to the specified success URI

return (mapping.findForward("SayHello"));

2.5  创建模型组件
在上一节已经讲过,Action类会访问模型组件。本例中模型组件为一JavaBean: PersonBean。例程2-5是PersonBean的源代码:

例程2-5  PersonBean.java

package hello;

public class PersonBean {

 

    private String userName = null;

 

    public String getUserName() {

        return this.userName;

    }

    public void setUserName(String userName) {

        this.userName = userName;

    }

 

    /**

     * This is a stub method that would be used for the Model to save

     * the information submitted to a persistent store. In this sample

     * application it is not used.

     */

    public void saveToPersistentStore() {

 

        /*

         * This is a stub method that might be used to save the person's

         * name to a persistent store(i.e. database) if this were a real application.

         *

         * The actual business operations that would exist within a Model

         * component would depend upon the requirements of the application.

         */

    }

}

 

PersonBean是一个非常简单的JavaBean,它包括一个userName属性,以及相关的get/set方法。此外,它还有一个业务方法saveToPersistentStore()。本例中并没有真正实现这一方法。在实际应用中,这个方法可以用来把JavaBean的属性保存在持久化存储系统中,如数据库或文件系统。

通过这个简单的例子,读者可以进一步理解Struts框架中使用模型组件的一大优点,它把业务逻辑的实现和应用的其他部分分离开来,可以提高整个应用的灵活性、可重用性和可扩展性。如果模型组件的实现发生改变,例如本来把JavaBean的属性保存在MySQL数据库中,后来改为保存在Oracle数据库中,此时Action类不需要作任何变动。不仅如此,即使模型组件由JavaBean改为EJB,运行在远程应用服务器上,也不会对Action类造成任何影响。

2.6  创建存放常量的Java文件
根据2.4.5小节,HelloAction类和视图组件之间通过HttpServletRequest的setAttribute()和getAttribute()方法来共享request范围内的数据。下面再看一下HelloAction类调用HttpServletRequest的setAttribute()方法的细节。

当HelloAction类调用HttpServletRequest的setAttribute()方法,向hello.jsp传递PersonBean对象时,需要提供一个名为“personbean”的属性key:

request.setAttribute("personbean",pb);

 

hello.jsp通过这个名为“personbean”的属性key来读取PersonBean对象:

<logic:present name="personbean" scope="request">

     <h2>

       Hello <bean:write name="personbean" property="userName" />!<p>

     </h2>

</logic:present>

 

对于Struts应用,提倡将这些属性key常量定义在一个Java文件Constants.java中,例程2-6显示了它的源程序。

例程2-6  Constants.java

package hello;

public final class Constants {

   /**

     * The application scope attribute under which our user database

     * is stored.

     */

    public static final String PERSON_KEY = "personbean";

}

 

这样,HelloAction类可以按以下方式来调用HttpServletRequest的setAttribute()方法:

request.setAttribute( Constants.PERSON_KEY, pb);

 

把一些常量定义在Constants.java中可以提高Action类的独立性,当属性key常量值发生改变,只需要修改Constants.java文件,不需要修改Action类。

此外,在本例中,把PersonBean对象保存在HttpServletRequest对象中。对于其他实际的Web应用,也可以根据需要把JavaBean对象保存在HttpSession对象中。

2.7  创建配置文件
2.7.1  创建Web应用的配置文件
对于Struts应用,它的配置文件web.xml应该对ActionServlet类进行配置,此外,还应该声明Web应用所使用的Struts标签库,本例中声明使用了三个标签库: Struts Bean、Struts HTML和Struts Logic标签库。例程2-7为web.xml的源代码。

例程2-7  web.xml

<?xml version="1.0" encoding="UTF-8"?>

 

<!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>HelloApp Struts Application</display-name>

 

<!-- Standard Action Servlet Configuration  -->

  <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>

     <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>hello.jsp</welcome-file>

  </welcome-file-list>

 

  <!-- Struts Tag Library Descriptors -->

  <taglib>

    <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>

    <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>

  </taglib>

 

  <taglib>

    <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>

    <taglib-location>/WEB-INF/struts-html.tld</taglib-location>

  </taglib>

 

  <taglib>

    <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>

    <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>

  </taglib>

 

</web-app>

 

2.7.2  创建Struts框架的配置文件
正如前面提及的,Struts框架允许把应用划分成多个组件,提高开发速度。而Struts框架的配置文件struts-config.xml可以把这些组件组装起来,决定如何使用它们。例程2-8是helloapp应用的struts-config.xml文件的源代码。

例程2-8  struts-config.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>

 

<!DOCTYPE struts-config PUBLIC

          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"

          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

 

<!--

     This is the Struts configuration file for the "Hello!" sample application

-->

 

<struts-config>

 

    <!-- ======== Form Bean Definitions =================================== -->

    <form-beans>

        <form-bean name="HelloForm" type="hello.HelloForm"/>

    </form-beans>

 

  <!-- ========== Action Mapping Definitions ============================== -->

  <action-mappings>

    <!-- Say Hello! -->

    <action    path      = "/HelloWorld"

               type      = "hello.HelloAction"

               name      = "HelloForm"

               scope     = "request"

               validate  = "true"

               input     = "/hello.jsp"

     >

        <forward name="SayHello" path="/hello.jsp" />

    </action>

  </action-mappings>

 

  <!-- ========== Message Resources Definitions =========================== -->

  <message-resources parameter="hello.application"/>

 

</struts-config>

 

以上代码对helloapp应用的HelloForm、HelloAction和消息资源文件进行了配置,首先通过<form-bean>元素配置了一个ActionForm Bean,名叫HelloForm,它对应的类为hello.HelloForm:

<form-bean name="HelloForm" type="hello.HelloForm"/>

接着通过<action>元素配置了一个Action组件:

<action    path      = "/HelloWorld"

          type      = "hello.HelloAction"

          name     = "HelloForm"

          scope     = "request"

          validate   = "true"

             input     = "/hello.jsp"

        <forward name="SayHello" path="/hello.jsp" />

</action>

 

<action>元素的path属性指定请求访问Action的路径,type属性指定Action的完整类名,name属性指定需要传递给Action的ActionForm Bean,scope属性指定ActionForm Bean的存放范围,validate属性指定是否执行表单验证,input属性指定当表单验证失败时的转发路径。<action>元素还包含一个<forward>子元素,它定义了一个请求转发路径。

本例中的<action>元素配置了HelloAction组件,对应的类为hello.HelloAction,请求访问路径为“HelloWorld”,当Action类被调用时,Struts框架应该把已经包含表单数据的HelloForm Bean传给它。HelloForm Bean存放在request范围内,并且在调用Action类之前,应该进行表单验证。如果表单验证失败,请求将被转发到接收用户输入的网页hello.jsp,让用户纠正错误。

 

struts-config.xml文件最后通过<message-resources>元素定义了一个Resource Bundle:

<message-resources parameter="hello.application"/>

 

<message-resources>元素的parameter属性指定Resource Bundle使用的消息资源文件。本例中parameter属性为“hello.application”,表明消息资源文件名为“application.properties”,它的存放路径为WEB-INF/classes/hello/application.properties。

2.8  发布和运行helloapp应用
helloapp应用作为Java Web应用,它的目录结构应该符合Sun公司制定的Java Web应用的规范,此外,由于helloapp应用使用了Struts框架,因此应该把Struts框架所需的JAR文件和标签库描述文件TLD文件包含进来。访问http://jakarta.apache.org/builds,可以下载最新的Struts软件包,把struts压缩文件解压后,在其lib子目录下提供了Struts框架所需的JAR文件:

l         commons-beanutils.jar

l         commons-collections.jar

l         commons-digester.jar

l         commons-fileupload.jar

l         commons-logging.jar

l         commons-validator.jar

l         jakarta-oro.jar

l         struts.jar

 

在Struts软件包的lib子目录下还提供了所有的Struts标签库描述TLD文件:

l         struts-bean.tld

l         struts-html.tld

l         struts-logic.tld

l         struts-nested.tld

l         struts-tiles.tld

 

图2-4显示了helloapp应用的目录结构。

图2-4  helloapp应用的目录结构

 

helloapp应用的Java源文件位于helloapp/src目录下,编译这些Java源文件时,应该把Servlet API的JAR文件以及Struts的struts.jar文件加到classpath中。如果在本地安装了Tomcat服务器,假定Tomcat的根目录为<CATALINA_HOME>,在<CATALINA_HOME>/common/lib目录下提供了servlet-api.jar文件。

在本书配套光盘的sourcecode/helloapp/version1/helloapp目录下提供了该应用的所有源文件,只要把整个helloapp子目录拷贝到<CATALINA_HOME>/webapps下,就可以按开放式目录结构发布这个应用。

如果helloapp应用开发完毕,进入产品发布阶段,应该将整个Web应用打包为WAR文件,再进行发布。在本例中,也可以按如下步骤在Tomcat服务器上发布helloapp应用。

(1)在DOS下转到helloapp应用的根目录。

(2)把整个Web应用打包为helloapp.war文件,命令如下:

jar cvf  helloapp.war  *.*

(3)把helloapp.war文件拷贝到<CATALINA_HOME>/webapps目录下。

(4)启动Tomcat服务器。Tomcat服务器启动时,会把webapps目录下的所有WAR文件自动展开为开放式的目录结构。所以服务器启动后,会发现服务器把helloapp.war展开到<CATALINA_HOME> /webapps/helloapp目录中。

(5)通过浏览器访问http://localhost:8080/helloapp/hello.jsp。

2.8.1  服务器端装载hello.jsp的流程
在Tomcat服务器上成功发布了helloapp应用后,访问http://localhost:8080/helloapp/hello.jsp,会看到如图2-5所示的网页。服务器端装载hello.jsp网页的流程如下。

(1)<bean:message>标签从Resource Bundle中读取文本,把它输出到网页上。

(2)<html:form>标签在request范围中查找HelloForm Bean。如果存在这样的实例,就把HelloForm对象中的userName属性赋值给HTML表单的userName文本框。由于此时还不存在HelloForm对象,所以忽略这项操作。

(3)把hello.jsp的视图呈现给客户。

图2-5  直接访问hello.jsp的输出网页

2.8.2  表单验证的流程
在hello.jsp网页上,不输入姓名,直接单击【Submit】按钮,会看到如图2-6所示的网页。

图2-6  表单验证失败的hello.jsp网页

当客户提交HelloForm表单时,请求路径为“/HelloWorld.do”:

<html:form action="/HelloWorld.do" focus="userName" >

服务器端执行表单验证流程如下。

(1)Servlet容器在web.xml文件中寻找<url-pattern>属性为“*.do”的<servlet-mapping>元素:

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

(2)Servlet容器依据以上<servlet-mapping>元素的<servlet-name>属性“action”,在web.xml文件中寻找匹配的<servlet>元素:

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

</servlet>

(3)Servlet容器把请求转发给以上<servlet>元素指定的ActionServlet,ActionServlet依据用户请求路径“/HelloWorld.do”,在Struts配置文件中检索path属性为“/HelloWorld”的<action>元素:

<action    path      = "/HelloWorld"

          type      = "hello.HelloAction"

          name      = "HelloForm"

          scope     = "request"

          validate  = "true"

          input     = "/hello.jsp"

>

        <forward name="SayHello" path="/hello.jsp" />

</action>

 

更确切的说,ActionServlet此时检索的是ActionMapping对象,而不是直接访问Struts配置文件中的<action>元素。因为在ActionServlet初始化的时候,会加载Struts配置文件,把各种配置信息保存在相应的配置类的实例中,例如<action>元素的配置信息存放在ActionMapping对象中。

 

(4)ActionServlet根据<action>元素的name属性,创建一个HelloForm对象,把客户提交的表单数据传给HelloForm对象,再把HelloForm对象保存在<action>元素的scope属性指定的request范围内。

(5)由于<action>元素的validate属性为true,ActionServlet调用HelloForm对象的validate()方法执行表单验证:

public ActionErrors validate(ActionMapping mapping,

                                 HttpServletRequest request) {

        ActionErrors errors = new ActionErrors();

 

        if ((userName == null) || (userName.length() < 1))

            errors.add("username", new ActionMessage("hello.no.username.error"));

 

        return errors;

}

(6)HelloForm对象的validate()方法返回一个ActionErrors对象,里面包含一个ActionMessage对象,这个ActionMessage对象中封装了错误消息,消息key为“hello.no.username.error”,在Resource Bundle中与值匹配的消息文本为:

hello.no.username.error=Please enter a <i>UserName</i> to say hello to!

 

(7)ActionServlet把HelloForm的validate()方法返回的ActionErrors对象包存在request范围内,然后根据<action>元素的input属性,把客户请求转发给hello.jsp。

(8)hello.jsp的<html:errors>标签从request范围内读取ActionErrors对象,再从ActionErrors对象中读取ActionMessage对象,把它包含的错误消息显示在网页上。

2.8.3  逻辑验证失败的流程
接下来在hello.jsp的HTML表单中输入姓名“Monster”,然后单击【Submit】按钮。当服务器端响应客户请求时,验证流程如下。

(1)重复2.8.2节的步骤1至4。

 

----------------------------------------------------------------------------

 

Struts框架
struts框架具有组件的模块化,灵活性和重用性的优点,同时简化了基于MVC的web应用程序的开发。
本章详细讨论struts架构。我们将看到struts是如何清晰地区分控制,事务逻辑和外观,从而简化了开发应用程序过程的。我们还将介绍struts提供的类如何使得开发工作更加简单,这些类包括:
控制程序流程的类
实现和执行程序事务逻辑的类
自定义的标 记库使得创建和验证HTML表单更加容易
1.Struts压缩包内容
文件夹jakarta-struts-1.0.2包含两个目录,lib和webapps。在lib目录中有使用struts创建应用程序时所需的文件:
文件 描述
jdbc2_0-stdext.jar 包含JDBC2.0 Optional Package API类。如果我们要使用struts提供的数据资源,就需要将这个文件拷贝到WEB-INFlib下
Struts.jar 包含struts中所有的java类。同样也需要拷贝到WEB-INFlib下
*.tld 标记库描述器文件,描述了多个struts标记库中的自定义标记。同样要拷贝到WEB-INFlib下
在webapps目录下有如下文件:
Web应用程序 描述
Struts-blank.war 一个简单的web应用程序
Struts-documentation.war 包含struts站点上所有struts文档
Struts-example.war Struts很多特性的示范
Struts-exercisetaglib.war 主要用于对自定义标签库进行增加而使用的测试页,但也可以示范如何使用struts标记
Struts-template.war 包含struts模板标记的介绍和范例
Struts-upload.war 一个简单的例子,示范如何使用struts框架上传文件
2.Struts体系结构
让我们从MVC角度观察struts框架中的组件

框架中三个部分:模型,视窗和控制器。
模型
在struts框架中,模型分为两个部分:
系统的内部状态
可以改变状态的操作(事务逻辑)
内部状态通常由一组ActinForm JavaBean表示。根据设计或应用程序复杂度的不同,这些Bean可以是自包含的并具有持续的状态,或只在需要时才获得数据(从某个数据库)。
大型应用程序通常在方法内部封装事务逻辑(操作),这些方法可以被拥有状态信息的bean调用。比如购物车bean,它拥有用户购买商品的信息,可能还有checkOut()方法用来检查用户的信用卡,并向仓库发定货信息。
小型程序中,操作可能会被内嵌在Action类,它是struts框架中控制器角色的一部分。当逻辑简单时这个方法很适合。
建议用户将事务逻辑(要做什么)与Action类所扮演的角色(决定做什么)分开。
视窗
由JSP建立,struts包含扩展自定义标签库,可以简化创建完全国际化用户界面的过程。
控制器
struts中,基本的控制器组件是ActionServlet类中的实例servelt,实际使用的servlet在配置文件中由一组映射(由ActionMapping类进行描述)进行定义。
3.Struts框架中的组件
(由于ROSE工具还未能下载,只能找来这幅图,它说明了一定问题,特别是ActionErrors,但它并没有将ActionMapping,JSP和Tag Library包含进来,有时间作完替换)
框架中所使用的组件:
ActionServlet 控制器
ActionClass 包含事务逻辑
ActionForm 显示模块数据
ActionMapping 帮助控制器将请求映射到操作
ActionForward 用来指示操作转移的对象
ActionError 用来存储和回收错误
Struts标记库 可以减轻开发显示层次的工作
下面我们看看各自在框架中所扮演的角色和责任。
3.1 Struts配置文件
这是将struts组件结合在一起的东东:struts-config.xml。默认值
WEB-INFstruts-config.xml。配置文件可以定义:
全局转发
ActionMapping类
ActionForm bean
JDBC数据源
配置全局转发
全局转发用来在JSP页之间创建逻辑名称映射。转发都可以通过对调用操作映射的实例来获得,例如:
actionMappingInstace.findForward(“logicalName”);
全局转发的例子:(所有的例子我没有进行解释,一是结合表可以理解,二是例子大部分来自系列四的示例,你应该在作完实验后,再来看一遍)
<global-forwards>
<forward name="bookCreated" path="/BookView.jsp"/>
</global-forwards>
属性 描述
Name 全局转发的名字
Path 与目标URL的相对路径

配置ActionMapping
ActionMapping对象帮助进行框架内部的流程控制,它们可将请求URI映射到Action类,并且将Action类与ActionForm bean相关联。ActionServlet在内部使用这些映射,并将控制转移到特定Action类的实例。所有Action类使用execute()方法实现特定应用程序代码,返回一个ActionForward对象,其中包括响应转发的目标资源名称。例如:
<action-mappings>
<action path="/createBook"
type="BookAction"
name="bookForm"
scope="request"
input="/CreateBook.jsp"
validate=”true”>
</action>
<forward name=”failure” path=”/CreateBook.jsp”/>
<forward name=”cancel” path=”/index.jsp”/>
</action-mappings>
属性 描述
Path Action类的相对路径
Name 与本操作关联的Action bean的名称
Type 连接到本映射的Action类的全称(可有包名)
Scope ActionForm bean的作用域(请求或会话)
input 输入表单的路径,指向bean发生输入错误必须返回的控制
validate 设置为true,则在调用Action对象上的execute()方法前,ActionServlet将调用ActionForm bean的validate()方法来进行输入检查
通过<forward>元素,可以定义资源的逻辑名称,该资源是Action类的响应要转发的目标。
属性 描述
Id ID
ClassName ActionForward类的完全限定名,默认是org.apache.struts.action.ActionForward
Name 操作类访问ActionForward时所用的逻辑名
Path 响应转发的目标资源的路径
redirect 若设置为true,则ActionServlet使用sendRedirect()方法来转发资源

配置ActionForm Bean
ActionServlet使用ActionForm来保存请求的参数,这些bean的属性名称与HTTP请求参数中的名称相对应,控制器将请求参数传递到ActionForm bean的实例,然后将这个实例传送到Action类。例子:
<form-beans>
<form-bean name="bookForm" type="BookForm"/>
</form-beans>
属性 描述
Id ID
className ActionForm bean的完全限定名,默认值是org.apache.struts.action.ActionFormBean
Name 表单bean在相关作用域的名称,这个属性用来将bean与ActionMapping进行关联
Type 类的完全限定名

配置JDBC数据源
用<data-sources>元素可以定义多个数据源。
属性 描述
Id ID
Key Action类使用这个名称来寻找连接
Type 实现JDBC接口的类的名称
下面属性需要<set-property>元素定义,在框架1.1版本中已不在使用,但你可用<data-source>元素。例子:
<data-sources>
<data-source id=”DS1”
key=”conPool”
type=”org.apache.struts.util.GenericDataSource”
<set-property id=”SP1”
autoCommit="true"
description="Example Data Source Configuration"
driverClass="org.test.mm.mysql.Driver"
maxCount="4"
minCount="2"
url="jdbc:mysql://localhost/test"
user="struts"
password="wrox" />
<data-source/>
</data-sources>
属性 描述
desciption 数据源的描述
autoCommit 数据源创建的连接所使用的默认自动更新数据库模式
driverClass 数据源所使用的类,用来显示JDBC驱动程序接口
loginTimeout 数据库登陆时间的限制,以秒为单位
maxCount 最多能建立的连接数目
minCount 要创建的最少连接数目
password 数据库访问的密码
readOnly 创建只读的连接
User 访问数据库的用户名
url JDBC的URL
通过指定关键字名称,Action类可以访问数据源,比如:
javax.sql.DataSource ds = servlet.findDataSource(“conPool”);
javax.sql.Connection con = ds.getConnection();

3.2 ActionServlet类
框架中的控制器组件是有org.apache.struts.action.ActionServlet类实现的,这个类是javax.servlet.http.HttpServlet类的扩展。
Struts controller基本功能是:
1. 截获用户的Http请求
2. 把这个请求映射到相应的Action类,如果这是此类收到的第一个请求,将初始化实例并
缓存。
3. 创建或发现一个ActionForm bean实例(看配置文件是否定义),然后将请求过程移植到
bean.
4. 调用Action实例的execute()方法并将ActioForm bean,Action Mapping对象,request
和response对象传给它。
如:public ActionForword execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
5.execute返回一个ActionForword对象,此对象连接到相应的jsp页面.
ActionServlet配置
我们需要在web.xml中声明ActionServlet,并且将它配置成启动时进行加载。以下为可以配置的初始化参数:
参数 默认值 描述
application null 应用程序的资源集合的类
bufferSize 4096 文件上传的缓冲区大小
config /WEB-INF/struts-config.xml 配置文件的位置和名称
content Text/html 默认的内容类型
debug 0 程序调试的级别
detail 0 程序调试细节的级别
factory null 消息资源工厂,用于国际化中解释消息资源
formBean org.apache.struts.action.ActionFormBean 封装ActionForm bean信息的类的名称
forward org.apache.struts.action.ActionForward 封装ActionForward对象信息的类的名称
locale true 为true,将在用户会话中存储一个本地对象
mapping org.apache.struts.action.ActionForward 封装ActionMapping信息的类的名称
maxFileSize 250M 上传文件的最大尺寸
multipartClass org.apache.struts.action.ActionForward 处理多部分请求的类的名称
noCache False HTTP标头是否要设置为禁止缓存
Null True 设置为true,对于无效的信息关键字将返回null
tempDir 作为一个servlet参数提供给程序的工作目录处理下载文件是使用的临时工作目录
validate True 是否使用新格式的配置文件
validating True 是否对配置文件进行有效性分析
大多数情况下,标准的servlet就能够满足用户需要。
第一次收到特定请求的URI时,ActionServlet将适当的Action类进行实例化,然后ActionServlet在Action类实例中以servlet为变量名存储一个引用。当被实例化后,Action类会被暂存以备再用。
ActionServlet也提供一些方法,由Action类用来访问数据源和转发目标之类的资源。
ActionServlet方法
ActinServlet提供了一组能够被Action对象使用的方法。
Struts API的全部信息在struts-documentation.war中可以找到。动态的添加或删除,这些方法只影响应用程序当前的实例:
public void addFormBean(ActionFormBean formBean)
public void removeFormBean(ActionFormBean formBean)
public void addForward(ActionForward actionForward)
public void removeForward(ActionForward actionForward)
public void addMapping(ActionMapping actionMapping)
public void removeMapping(ActionMapping actionMapping)
根据名称查找对象:
public ActionFormBean findFormBean(String name)
public ActionForward findForward(String name)
public ActionMapping findMapping(String name)
用来处理数据源:
public void addDataSource(String key , DataSource ds)
public DataSource findDataSource(String key)
我们还可以:
使用destroy()方法结束ActionServlet
使用reload()方法从struts配置文件将信息重新加载。

3.3 ActionMapping类
将特定请求映射到特定Action的相关信息存储在ActionMapping中,ActionServelt将ActionMapping传送到Action类的execute()方法,Action将使用ActionMapping的findForward()方法,此方法返回一个指定名称的ActionForward,这样Action就完成了本地转发。若没有找到具体的ActionForward,就返回一个null.
public ActionForward findForward(String name)
可在映射中动态添加ActionForward:
public void addForward(ActionForward forward)
可返回与映射关联的表单bean:
public String getName()
可返回映射的属性域(会话或请求)
public String getScope()

3.4 Action类
Action类真正实现应用程序的事务逻辑,它们负责处理请求。在收到请求后,ActionServlet会:
为这个请求选择适当的Action
如果需要, 创建Action的一个实例
调用Action的execute()方法
如果ActionServlet不能找到有效的映射,它会调用默认的Action类(在配置文件中定义)。如果找到了ActionServlet将适当的ActionMapping类转发给Action,这个Action使用ActionMapping找到本地转发,然后获得并设置ActionMapping属性。根据servlet的环境和被覆盖的execute()方法的签名,ActionServlet也会传送ServletRequest对象或HttpServletRequest对象。
所有Action类都扩展org.apache.struts.action.Action类,并且覆盖类中定义的某一个execute()方法。有两个execute()方法:
处理非HTTP(一般的)请求:
public ActionForward execute(ActionMapping action,
AcionForm form,
ServletRequest request,
ServletResponse response)
throws IOException,ServletException
处理HTTP请求:
public ActionForward execute(ActionMapping action,
AcionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException,ServletException
Action类必须以“线程安全”的方式进行编程,因为控制器会令多个同时发生的请求共享同一个实例,相应的,在设计Action类时就需要注意以下几点:
不 能使用实例或静态变量存储特定请求的状态信息, 它们会在同一个操作中共享跨越请求的全局资源
如果要访问的资源(如JavaBean和会话变量)在并行访问时需要进行保护,那么访问就要进行同 步
Action类的方法
除了execute()方法外,还有以下方法:
可以获得或设置与请求相关联的区域:
public Locale getLocale(HttpServletRequest request)
public void setLocale(HttpServletRequest request,Locale locale)
为应用程序获得消息资源:
public MessageResources getResources()
检查用户是否点击表单上的“取消”键,如果是,将返回true:
public Boolean isCancelled(HttpServletRequest request)
当应用程序发生错误时,Action类能够使用下面方法存储错误信息:
public void saveErrors(HttpServletRequest request,ActionErrors errors)
ActionError实例被用来存储错误信息,这个方法在错误关键字下的请求属性列表中存储ActionError对象。通过使用在struts标记库中定义的自定义标记,JSP页能够显示这些错误信息,稍后我们就介绍。

3.5 ActionForm类
框架假设用户在应用程序中为每个表单都创建了一个ActionForm bean,对于每个在struts-config.xml文件中定义的bean,框架在调用Action类的execute()方法之前会进行以下操作:
在相关联的关键字下, 它检查用于适当类的bean实例的用户会话,如果在会话中没有可用的bean,它就会自动创建一个新的bean并添加到用户的会话中。
对于请求中每个与bean属性名 称对应的参数, Action调用相应的设置方法。
当Action execute()被调用时, 最新的ActionForm bean传送给它,参数值就可以立即使用了。
ActionForm类扩展org.apache.struts.action.ActionForm类,程序开发人员创建的bean能够包含额外的属性,而且ActionServlet可能使用反射(允许从已加载的对象中回收信息)访问它。
ActionForm类提供了另一种处理错误的手段,提供两个方法:
Public ActionErrors validate(ActionMappin mapping,
ServletRequest request)
Public ActionErrors validate(ActionMappin mapping,
HttpServletRequest request)
你应该在自己的bean里覆盖validate()方法,并在配置文件里设置<action>元素的validate为true。在ActionServlet调用Action类前,它会调用validate(),如果返回的ActionErrors不是null,则ActinForm会根据错误关键字将ActionErrors存储在请求属性列表中。
如果返回的不是null,而且长度大于0,则根据错误关键字将实例存储在请求的属性列表中,然后ActionServlet将响应转发到配置文件<action>元素的input属性所指向的目标。
如果需要执行特定的数据有效性检查,最好在Action类中进行这个操作,而不是在ActionForm类中进行。
方法reset()可将bean的属性恢复到默认值:
public void reset(ActionMapping mapping,HttpServletRequest request)
public void reset(ActionMapping mapping,ServletRequest request)
典型的ActionFrom bean只有属性的设置与读取方法(getXXX),而没有实现事务逻辑的方法。只有简单的输入检查逻辑,使用的目的是为了存储用户在相关表单中输入的最新数据,以便可以将同一网页进行再生,同时提供一组错误信息,这样就可以让用户修改不正确的输入数据。而真正对数据有效性进行检查的是Action类或适当的事务逻辑bean。

3.6 ActionForward类
目的是控制器将Action类的处理结果转发至目的地。
Action类获得ActionForward实例的句柄,然后可用三种方法返回到ActionServlet,所以我们可以这样使用findForward():
ActionServlet根据名 称获取一个全局转发
ActionMapping实例被传送到execute()方法, 并根据名称找到一个本地转发
另一种是调用下面的一个构造器来创建它们自己的一个实例:
public ActionForward()
public ActionForward(String path)
public ActionForward(String path,Boolean redirect)

抱歉!评论已关闭.