Skip to content

6. 示例 05 – 输入表单

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

6.1. NetBeans 项目

在 [1] 中,该项目:

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

在 [2] 中,入口页面

6.2. 配置

[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>
  <!-- internationalization -->
  <constant name="struts.custom.i18n.resources" value="messages" />
  <!-- default package -->
  <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>
  <!-- equity 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 行:定义 [Enter] 操作。该操作未关联任何类。响应始终为视图 [/views/Enter.jsp]
  • 第 24–26 行:定义 [Confirm] 操作。该操作关联了 [actions.Confirm] 类。响应始终是视图 [/views/Confirmation.jsp]

6.3. [确认] 操作

其代码如下:


package actions;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class Confirmer extends ActionSupport{
 
  // model
  private String nom;
 
  // getters and setters
 
  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

这些消息键在 [Entry.jsp] 和 [Confirmation.jsp] 视图中均被使用。

6.5. 视图

6.5.1. [Entry.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”数据,是因为将数据发送至服务器的 HTTP 操作称为 POST。数据以字符串形式发送:param1=value1&param2=value2&... 我们已经在示例 02 的第 3.5 节中遇到过这种字符串。 在这两种情况下,Struts 2 都会以相同的方式处理参数字符串。参数的值会被注入到正在执行的 Action 中,并存入与参数同名的字段中。提交的数据会发送给谁?默认情况下,会发送给显示表单的 Action,即这里的 Saisir Action [5]。您也可以使用 action 属性指定另一个 Action,例如这里的 [Confirmer] Action。
  • 第 12 行:<s:textfield ...> 标签显示输入字段 [3]。其 key 属性指定了将显示在输入字段左侧的标签键。因此,该标签会在 [messages.properties] 文件中被查找。name 属性是将被提交的参数名称。与该参数关联的值将是输入字段中输入的文本。
  • 第 13 行:<s:submit ...> 标签显示按钮 [4]。其 key 属性指定了将显示在按钮上的标签的键名。因此,该标签是从 [messages.properties] 文件中获取的。提交按钮会触发表单向某个操作提交。我们之前提到,由于 <s:form> 标签的 action 属性,此操作是 [Confirm]。 <s:submit> 标签的 action 属性允许您根据需要指定不同的操作。在此,我们将操作设置为 [Confirm]。该按钮有一个默认参数名称:action:action_name,此处为 action:Confirm。与该参数关联的值即为按钮标签。最终,当用户点击 [Validate] 按钮时,提交给 [Confirm] 操作的参数字符串将为:

?name=xx&action:Confirm=Validate

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

6.5.2. [Confirmation.jsp] 视图

从视觉上看,它如下所示:

我们输入一个名字并提交表单。随后收到响应 [1],即 [Confirmation.jsp] 视图。显示在 [2] 处的 URL 是 [Confirm] 操作的地址。在上例中,提交了以下字符串:

name=bernard&action:Confirm=Validate

action:Confirm 参数使 Struts 2 能够将请求路由到正确的操作,在本例中即 [Confirm] 操作。随后,name 参数的值将被注入到 [Confirm] 操作的 name 字段中。

[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.title1
  • 第 10 行:显示消息文件 [3] 中找到的键标签 confirm.title2
  • 第 12 行:显示已执行的 [Confirm] 操作的 name 属性。
  • 第 14 行:创建指向 [Enter] 操作的链接。我们之前见过的 <s:url> 标签将根据浏览器的 URL [2] 生成。 路径将采用 [2] 中的 http://localhost:8084/exemple-05/actions,而操作则取自 action 属性,本例中为 Enter。因此,链接的 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]。因此,[提交] 操作被执行。让我们看看 [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>

[Enter] 操作未与任何操作关联。因此,[Entry.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 行显示了输入字段。其内容通过 name 属性进行初始化。回顾一下前面关于 <s:property> 标签工作原理的说明:

<s:property name="property"> 标签允许您写入名为 ActionContext 的对象的某个属性的值。该对象包含:

  1. 与已执行操作相关联的类的属性。
  2. 当前请求的属性,表示为 <s:property name="#request['key']">
  3. 用户会话的属性,表示为 <s:property name="#session['key']">
  4. 应用程序本身的属性,表示为 <s:property name="#application['key']">
  5. 客户端浏览器发送的参数,表示为 <s:property name="#parameters['key']">
  6. 语法 <s:property name="#attr['key']"> 按页面、请求、会话和应用程序的顺序,依次显示在这些位置中检索到的对象的值。

此处属于情况 1。[Enter] 操作没有关联的类。因此,name 属性不存在。随后,输入字段中将显示一个空字符串。

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