Skip to content

6. 示例 05 – 输入表单

我们将通过一个简单的示例来介绍输入表单的概念。

6.1. NetBeans 项目

在 [1] 中,该项目:

  • 视图 [Saisie.jsp]、[Confirmation.jsp]
  • 配置文件 [struts.xml]
  • 消息文件 [messages.properties]
  • 操作 [Confirmer.java]

在 [2] 中,输入页面

6.2. Configuration

文件 [struts.xml] 内容如下:


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
  <!-- 国际化 -->
  <constant name="struts.custom.i18n.resources" value="messages" />
  <!-- 默认包 -->
  <package name="default" namespace="/" extends="struts-default">
    <default-action-ref name="index" />
    <action name="index">
      <result type="redirectAction">
        <param name="actionName">Saisir</param>
        <param name="namespace">/actions</param>
      </result>
    </action>
  </package>
  <!-- 操作包 -->
  <package name="actions" namespace="/actions" extends="struts-default">
    <action name="Saisir">
      <result name="success">/vues/Saisie.jsp</result>
    </action>
    <action name="Confirmer" class="actions.Confirmer">
      <result name="success">/vues/Confirmation.jsp</result>
    </action>  
  </package>
</struts>
  • 第 20 行:URL 操作包 /actions/Action
  • 第 21-23 行:定义操作 [Saisir]。未关联任何类。响应始终是视图 [/vues/Saisie.jsp]
  • 第24-26行:定义操作[Confirmer]。该操作关联了类[actions.Confirmer]。响应始终是视图[/vues/Confirmation.jsp]

6.3. 操作 [Confirmer]

其代码如下:


package actions;

import com.opensymphony.xwork2.ActionSupport;

public class Confirmer extends ActionSupport{
  
  // 模型
  private String nom;
  
  // 获取器和设置器

  public String getNom() {
    return nom;
  }

  public void setNom(String nom) {
    this.nom = nom;
  }
  
}

该类仅有一个字段,即第8行中的字段及其get/set方法。

6.4. 消息文件

[messages.properties] 的内容如下:


saisie.texte=Formulaire de saisie
saisie.titre1=Saisie
saisie.titre2=Saisie
saisie.libelle=Tapez votre nom
saisie.valider=Valider
confirm.titre1=Confirmation
confirm.titre2=Confirmation
confirm.texte=Bonjour
confirm.retour=Retour au formulaire de saisie

这些消息键在 [Saisie.jsp] 和 [Confirmation.jsp] 这两个视图中被使用。

6.5. 视图

6.5.1. 视图 [Saisie.jsp]

其视觉效果如下:

其源代码如下:


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><s:text name="saisie.titre1"/></title>
  </head>
  <body>
    <h1><s:text name="saisie.titre2"/></h1>
    <s:form action="Confirmer">
      <s:textfield key="saisie.libelle" name="nom"/>
      <s:submit key="saisie.valider" action="Confirmer"/>
    </s:form>
  </body>
</html>
  • 第 7 行:显示键值消息 saisie.titre1 (输入) [1]。
  • 第10行:显示键值消息 saisie.titre2 (输入) [2]。
  • 第 11、14 行:标签 <s:form> 引入了一个 HTML 表单。该表单内的所有输入内容都将发送至 Web 服务器。 之所以称其为 postées,是因为向服务器发送数据时涉及的 Http 操作名为 POST。发送的数据以字符串形式呈现,即 param1=valeur1&param2=valeur2&... 我们在示例02的第3.5节中已经遇到过这个字符串。 在这两种情况下,Struts 2 对参数字符串的处理方式相同。参数 parami 的值 valeuri 会被注入到正在执行的 Action 中,并存入与参数 parami 同名的字段中。 提交的数据将发送给谁?默认情况下,发送给显示表单的动作,此处为动作 Saisir [5]。也可以使用 action 属性指定另一个动作,此处为动作 [Confirmer]。
  • 第 12 行:<s:textfield ...> 标签显示输入字段 [3]。其 key 属性指定了要在输入字段左侧显示的标签键。 因此,该标签名称将从文件 [messages.properties] 中查找。属性 name 是将被提交的参数名称。该参数的值即为输入框中输入的文本。
  • 第 13 行:<s:submit ...> 标签显示按钮 [4]。其属性 key 指定了要在按钮上显示的标签键。 因此,该标签名称会在文件 [messages.properties] 中进行查找。一个类型为 submit 的按钮会触发表单的 POST 动作。 我们前面提到,由于 <s:form> 标签的 action 属性,该操作是 [Confirmer]。 标签 <s:submit>action 属性允许在必要时指定另一个操作。在此,我们重新设置了操作 [Confirmer]。 该按钮有一个默认参数名称:action:nom_action,此处为 action:Confirmer。 该参数的值即为按钮的标签。最终,当用户点击按钮 [Valider] 时,发送到操作 [Confirmer] 的参数字符串将为:

?nom=xx&action:Confirmer=Valider

其中 xx 是用户在输入字段中输入的文本。

6.5.2. 视图 [Confirmation.jsp]

在视觉上如下所示:

我们输入一个名称并提交输入页面。随后得到响应 [1],即视图 [Confirmation.jsp] 的响应。 显示的URL为[2],对应的是操作[Confirmer]。在上例中,提交了以下字符串:

nom=bernard&action:Confirmer=Valider

参数 action:Confirmer 使 Struts 2 能够将请求定向到正确的操作,此处即操作 [Confirmer]。 随后,参数 nom 的值将被注入到操作 [Confirmer] 的字段 nom 中。

操作 [Confirmation.jsp] 的源代码如下:


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><s:text name="confirm.titre1"/></title>
  </head>
  <body>
    <h1><s:text name="confirm.titre2"/></h1>
    <s:text name="confirm.texte"/>&nbsp;
    <s:property value="nom"/> !
    <br/><br/>
    <a href="<s:url action="Saisir"/>"><s:text name="confirm.retour"/></a>
  </body>
</html>
  • 第 7 行:显示在消息文件 [1] 中找到的键名称 confirm.titre1
  • 第 10 行:显示在消息文件 [3] 中找到的键名称 confirm.titre2
  • 第 12 行:显示已执行的操作 [Confirmer] 的属性 nom
  • 第14行:创建指向操作[Saisir]的链接。此前已出现的标签<s:url>,将根据浏览器中的URL [2]生成。 路径将遵循 [2] http://localhost:8084/exemple-05/actions 的模式,而操作则由 action 属性决定,此处为 Saisir。 因此,链接的 URL 将为 http://localhost:8084/exemple-05/actions/Saisir.action。链接文本将是与键 confirm.retour [4] 关联的标签。

6.6. 测试

以下是两个请求:

在 [1] 中,输入一个名称并提交。在 [2] 中,显示确认页面。

在 [3] 中,点击返回表单的链接。在 [4] 中,显示结果。 以上内容已全部说明,唯独[3]到[4]的过渡部分除外。为何在[4]中找不到之前输入的姓名?

[3] 中的链接指向 URL [http://localhost:8084/exemple-05/actions/Saisir.action]。因此执行了操作 [Saisir]。让我们查看 [struts.xml] 中的配置:


<package name="actions" namespace="/actions" extends="struts-default">
    <action name="Saisir">
      <result name="success">/vues/Saisie.jsp</result>
    </action>
    <action name="Confirmer" class="actions.Confirmer">
      <result name="success">/vues/Confirmation.jsp</result>
    </action>  
</package>

操作 [Saisir] 未关联任何操作。因此视图 [Saisie.jsp] 会立即显示。让我们查看该视图的代码:


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><s:text name="saisie.titre1"/></title>
  </head>
  <body>
    <h1><s:text name="saisie.titre2"/></h1>
    <s:form>
      <s:textfield key="saisie.libelle" name="nom"/>
      <s:submit key="saisie.valider" action="Confirmer"/>
    </s:form>
  </body>
</html>

第 12 行显示了输入字段。其内容通过属性 nomname)进行初始化。回顾前文关于 <s:property> 标签工作原理的说明:

<s:property name="属性">标签用于写入名为ActionContext的对象的属性值。该对象包含:

  1. 与已执行操作相关联的类的属性。
  2. 当前请求的属性,标记为 <s:property name="#request['clé']">
  3. 用户会话的属性,标记为 <s:property name="#session['clé']">
  4. 应用程序本身的属性,标记为 <s:property name="#application['clé']">
  5. 客户端浏览器发送的参数,标记为 <s:property name="#parameters['clé']">
  6. <s:property name="#attr['clé']"> 表示从页面、请求、会话、应用程序中按此顺序查找对象的值。

此处属于情况1。操作[Saisir]没有关联的类。因此属性nom不存在。此时输入框中将显示一个空字符串。

若要在 [4] 中显示在 [1] 中输入的名称,我们将使用用户的会话。