Skip to content

2. strutspersonne 应用程序

我们已使用传统方法(Servlet 和 JSP 页面)实现了一个“person”应用程序。现在,我们将通过这个应用程序来介绍 Struts。

2.1. 应用程序的工作原理

让我们回顾一下我们开发的“person”应用程序是如何工作的。它由以下部分组成:

  • 一个Servlet。它负责处理所有应用程序逻辑。
  • 三个 JSP 页面:formulaire.personne.jspreponse.personne.jsp erreurs.personne.jsp

该应用程序的工作原理如下。可通过 URL http://localhost:8080/personne/main 访问。访问该 URL 时,将显示由 formulaire.personne.jsp 页面提供的表单:

Image

用户填写表单并点击 [提交] 按钮。[重置] 按钮用于将文档恢复至初始接收时的状态。[删除] 按钮为标准按钮。用户必须提供有效的姓名和年龄。若未满足此条件,系统将通过 JSP 页面 erreurs.personne.jsp 向用户返回错误页面。以下是一些示例:

对话 #1

请求
回复

如果您点击[返回表单]链接,您将看到表单处于您离开时的状态:

交流 #2

请求
响应

如果用户提交了有效数据,应用程序将通过 JSP 页面 response.personne.jsp 发送响应。

对话 #1

请求
回复

如果您点击[返回表单]链接,您将看到表单处于您离开时的状态:

交流 #2

请求
响应

2.2. 应用程序的 Struts 架构

我们将采用以下 Struts 架构:

  • 将有三个视图
  • 控制器将由 Struts 提供
  • FormBean 是负责存储视图 form.person.jsp 提交的表单值的类
  • FormAction 类负责处理 FormBean 的值,并指定要发送的响应页面:
    • 如果表单数据有误,则显示 errors.person.jsp 视图
    • 否则,将返回 response.personne.jsp 视图

对于开发人员而言,任务包括编写以下代码:

  • 三个视图
  • 与表单关联的 FormBean
  • 负责处理表单的 FormAction

2.3. 编译 Struts 应用程序所需的类

为了编译应用程序所需的类,我们将使用 JBuilder。JBuilder 配合使用的 JDK 并不包含 Struts 应用程序所需的类。我们可以按以下方式配置 JBuilder:

  • 工具 / 配置 JDK

Image

  • 使用 [添加] 按钮将 Struts 提供的 .jar 文件添加到 JBuilder 的类库中。如果您已将 Struts 压缩包解压到本地磁盘,可以将 <struts>/lib 文件夹中的所有 .jar 文件添加到 JBuilder 中:

Image

您可以将上述所有 .jar 文件添加到 JBuilder 的归档中。我们已经看到,Tomcat 也需要访问 Struts 归档。对于 Tomcat 4.x,您可以将 Struts .jar 文件放置在 <tomcat4>\common\lib 中。对于 Tomcat 5.x,您可以将它们放置在 <tomcat5>\shared\lib 中。 随后,您可以配置 JBuilder,使其在与 Tomcat 相同的位置查找 Struts .jar 文件。这就是前面提到的展示 JBuilder .jar 文件的屏幕截图中所做的操作。这些文件是从 <tomcat5>\shared\lib 目录中获取的

因此,如果 JBuilder 在编译类时报告无法找到 Struts 类,请检查以下两点:

  • 类名的拼写
  • JBuilder所使用的.jar文件。所有Struts .jar文件都必须包含在内。

2.4. strutspersonne 应用程序的视图

该应用程序的三个视图如下:

  • form.person.jsp:显示用于输入姓名和年龄的表单
  • response.personne.jsp:若输入值有效,则显示这些值
  • errors.person.jsp:显示任何错误

2.4.1. errors.personne.jsp 视图

该视图用于显示错误列表,定义如下:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
        <html:errors/>
    <html:link page="/formulaire.do">
            Retour au formulaire
        </html:link>    
  </body>
</html>

此代码中有两个新特性:

  1. 出现了 <html:XX/> 标签,这些并非 HTML 标签。您可以创建 JSP 标签库,当 JSP 页面转换为 Servlet 时,这些标签会被转换为 Java 代码。
  2. JSP 页面必须声明其使用的标签库。此处通过以下代码行进行声明:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

这一行提供了两条信息:

  • uri:控制库使用规则的文件位置。struts-html.tld 文件包含在 Struts 发行版中。在上例中,该文件位于 WEB-INF 文件夹内。
  • prefix:代码中用于修饰库标签的前缀标识符。这可避免同时使用多个标签库时可能出现的命名冲突。两个不同的库中可能存在名称相同的标签。通过为每个库指定不同的前缀,即可消除任何歧义。
  • <html:errors> 标签用于显示 Struts 控制器发送给它的错误列表。
  • <html:link> 标签生成一个指向 /C/page 的链接,其中
    • C 代表应用程序上下文
    • page 是该标签的 page 属性中指定的 URL

    <html:link page="/formulaire.do">
            Retour au formulaire
        </html:link>

将生成以下 HTML 代码:

<a href="/C/formulaire.do">Retour au formulaire</a>

其中 C 是应用程序上下文

2.4.2. 测试 errors.person.jsp 视图

  • errors.person.jsp 文件位于 strutspersonne 应用程序的 views 文件夹中:

Image

  • struts-html.tld 文件取自 Struts 发行版(<struts>/lib)并放置在 WEB-INF 目录下

Image

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

<struts-config>
    <action-mappings>
      <action
          path="/main"
          parameter="/vues/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/erreurs"
          parameter="/vues/erreurs.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>
</struts-config>

我们在配置文件中创建了一个新的 URL /errors,由 Struts 控制器进行处理。URL /errors.do 将被重定向到视图 /views/errors.person.jspstruts-config.xml 文件位于 WEB-INF 文件夹中。

  • 我们重启 Tomcat 以使新的 struts-config.xml 文件生效,然后请求 URL http://localhost:8080/strutspersonne/erreurs.do

Image

<html:errors/> 标签未输出任何内容。这是正常的;ForwardAction 并未生成该标签所期望的错误列表。尽管如此,上述响应表明我们的 JSP 视图至少在语法上是正确的;否则,我们会收到一个错误页面。让我们检查浏览器收到的 HTML 代码(查看/源代码):

<html>
    <head>
      <title>Personne - erreurs</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>        
    <a href="/strutspersonne/formulaire.do">Retour au formulaire</a>    
  </body>
</html>

请注意由 <html:link> 标签生成的链接。链接中已自动包含 /strutspersonne 上下文。这使得应用程序可以在不同上下文之间迁移(例如更换机器)时,无需修改由 <html:link> 生成的链接。

2.4.3. response.personne.jsp 视图

该视图用于确认表单中输入的值,内容如下:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<%
    // on récupère les données nom, age
  //String nom=(String)request.getAttribute("nom");
  String nom="jean";

  //String age=(String)request.getAttribute("age"); 
  String age="24"; 
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td><%= nom %>
      </tr>
        <tr>
          <td>Age</td>
        <td><%= age %>
      </tr>
    </table>      
    <br>
    <html:link page="/formulaire.do">
            Retour au formulaire
        </html:link>    
  </body>
</html>

该页面显示两项信息:[name] 和 [age],这些信息将由控制器通过预定义的请求对象传递给它。在此,我们进行了一项测试,即控制器将无法设置 [name] 和 [age] 的值。因此,我们使用任意值初始化这两项信息。此外,此处的表单返回链接也是通过 <html:link> 标签生成的。

2.4.4. 测试 response.personne.jsp 视图

  • reponse.personne.jsp 文件位于 strutspersonne 应用程序的 views 文件夹中:

Image

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

<struts-config>
    <action-mappings>
      <action
          path="/main"
          parameter="/vues/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/erreurs"
          parameter="/vues/erreurs.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/reponse"
          parameter="/vues/reponse.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>
</struts-config>

我们在配置文件中创建了一个新的 URL /reponse,由 Struts 控制器处理。URL /reponse.do 将重定向到视图 /vues/reponse.personne.jspstruts-config.xml 文件位于 WEB-INF 文件夹中。

  • 重启 Tomcat 以使新的 struts-config.xml 文件生效,随后访问 URL http://localhost:8080/strutspersonne/erreurs.do

Image

结果完全符合预期。

2.4.5. formulaire.personne.jsp 视图

该视图显示用于输入用户姓名和年龄的表单。其 JSP 代码如下:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
    <meta http-equiv="pragma" content="no-cache"> 
    <head>
      <title>Personne - formulaire</title>
    <script language="javascript">
        function effacer(){
          with(document.frmPersonne){
            nom.value="";
          age.value="";
        }
      }
    </script>
  </head>

  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <html:form action="/main" name="frmPersonne" type="istia.st.struts.personne.FormulaireBean">
          <table>
            <tr>
              <td>Nom</td>
            <td><html:text property="nom" size="20"/></td>
          </tr>
          <tr>
              <td>Age</td>
            <td><html:text property="age" size="3"/></td>
          </tr>
            <tr>
        </table>
        <table>
            <tr>
              <td><html:submit value="Envoyer"/></td>
            <td><html:reset value="Rétablir"/></td>
            <td><html:button property="btnEffacer" value="Effacer" onclick="effacer()"/></td>
          </tr>
        </table>
      </html:form>
    </center>
  </body>
</html>

我们看到错误视图中使用了 struts-html.tld 标签库。出现了新的标签:

html:form
既用于生成 HTML 标签 <form>,也用于向将处理此表单的控制器提供信息:
action
表单值将被发送到的 URL
name
HTML 表单的名称。这也是将用于存储表单值的 Bean 的名称
type
必须实例化以获取表单存储 Bean 的类名称
请注意,未指定用于将表单参数(GET/POST)发送至控制器的具体方法。可通过 method 属性进行指定。若该属性缺失,则默认使用 POST 方法。
html:text
用于生成 <input type="text" value="..."> 标签:
属性
表单 Bean 中将与输入字段关联的字段名称。当表单提交至服务器(客户端 → 服务器)时,Bean 字段将获取输入字段的值。当表单显示(服务器 → 客户端)时,Bean 字段中包含的值将显示在输入字段中。
html:submit
用于生成 HTML 标签 <input type="submit"...>
html:reset
用于生成 HTML 标签 <input type="reset"...>
html:button
用于生成 HTML 标签 <input type="button"...>

2.4.6. 与 formulaire.personne.jsp 表单关联的 Bean

  • 在 Struts 中,每个表单都必须关联一个 Bean,该 Bean 负责存储表单的值并在当前会话中维护这些值。Bean 是一个必须遵循特定语法的 Java 类。与表单关联的 Bean 必须继承 Struts 库中定义的 ActionForm 类:
public class FormulaireBean extends ActionForm {
  • Bean 的属性名称必须与表单字段(即表单中 <html:text> 标签的 property 属性)相对应。根据前一个表单的代码,该 Bean 因此必须包含两个名为 name age 的字段。
  • 对于表单中的每个字段 XX,Bean 必须定义两个方法:
    • public void setXX(Type value):用于为 XX 属性赋值
    • public getXX(Value type):用于获取 XX 字段的值

与前一个表单关联的 Bean 可以如下所示:

package istia.st.struts.personne;

import org.apache.struts.action.ActionForm;

public class FormulaireBean extends ActionForm {
   // name
  private String nom = null;
  public String getNom() {
    return nom;
  }
  public void setNom(String nom) {
    this.nom = nom;
  }

   // age
  private String age = null;
  public String getAge() {
    return age;
  }
  public void setAge(String age) {
    this.age = age;
  }
}

我们将使用 JBuilder 编译此类。

2.4.7. 测试 formulaire.personne.jsp 视图

formulaire.personne.jsp 文件位于 strutspersonne 应用程序的 views 文件夹中:

Image

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

<struts-config>
    <action-mappings>
      <action
          path="/main"
          parameter="/vues/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/erreurs"
          parameter="/vues/erreurs.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/reponse"
          parameter="/vues/reponse.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/formulaire"
          parameter="/vues/formulaire.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>
</struts-config>

在配置文件中,我们创建了一个新的 URL /form,由 Struts 控制器处理。URL /form.do 将重定向到视图 /views/form.person.jspstruts-config.xml 文件位于 WEB-INF 文件夹中。

  • 我们将 FormulaireBean 类放置在 WEB-INF/classes 目录下:

Image

  • 重启 Tomcat 以使新的 struts-config.xml 文件生效,然后访问 URL http://localhost:8080/strutspersonne/formulaire.do

Image

表单显示正常。我们可能好奇,散布在表单 JSP 代码中的 <html:XX> 标签是如何被“转换”的:

<html>
    <meta http-equiv="pragma" content="no-cache"> 
    <head>
      <title>Personne - formulaire</title>
    <script language="javascript">
        function effacer(){
          with(document.frmPersonne){
            nom.value="";
          age.value="";
        }
      }
    </script>
  </head>

  <body>
      <center>

        <h2>Personne - formulaire</h2>
      <hr>
      <form name="frmPersonne" method="post" action="/strutspersonne/main.do">
          <table>
            <tr>
              <td>Nom</td>
            <td><input type="text" name="nom" size="20" value=""></td>
          </tr>

          <tr>
              <td>Age</td>
            <td><input type="text" name="age" size="3" value=""></td>
          </tr>
            <tr>
        </table>
        <table>
            <tr>

              <td><input type="submit" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" name="btnEffacer" value="Effacer" onclick="effacer()"></td>
          </tr>
        </table>
      </form>
    </center>
  </body>
</html>

在生成的表单中,[重置]和[清除]按钮可以正常工作。[提交]按钮会重定向到 URL /strutspersonne/main.do。根据应用程序的 web.xml 文件,Struts 控制器将处理此请求。根据 struts-config.html 文件,控制器必须将请求重定向到视图 /vues/main.html。让我们试一试:

Image

一切运行如预期。我们仍需实际处理表单值,即编写一个 Action 类,将表单数据写入 FormBean 对象中。