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¶m2=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"/>
<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 行显示了输入字段。其内容通过属性 nom(name)进行初始化。回顾前文关于 <s:property> 标签工作原理的说明:
<s:property name="属性">标签用于写入名为ActionContext的对象的属性值。该对象包含:
- 与已执行操作相关联的类的属性。
- 当前请求的属性,标记为 <s:property name="#request['clé']">
- 用户会话的属性,标记为 <s:property name="#session['clé']">
- 应用程序本身的属性,标记为 <s:property name="#application['clé']">
- 客户端浏览器发送的参数,标记为 <s:property name="#parameters['clé']">
- <s:property name="#attr['clé']"> 表示从页面、请求、会话、应用程序中按此顺序查找对象的值。
此处属于情况1。操作[Saisir]没有关联的类。因此属性nom不存在。此时输入框中将显示一个空字符串。
若要在 [4] 中显示在 [1] 中输入的名称,我们将使用用户的会话。




