2. Struts 人员应用程序
我们之前曾采用经典方法(Servlet 和 JSP 页面)处理过一个人员管理应用程序。现在,我们将通过这个应用程序来介绍 Struts。
2.1. 应用程序的工作原理
在此回顾一下我们之前开发的“person”应用程序的工作原理。它由以下部分组成:
- 一个主Servlet。它负责处理应用程序的所有业务逻辑。
- 三个页面:JSP、formulaire.personne.jsp、reponse.personne.jsp、erreurs.personne.jsp
该应用程序的工作原理如下。可通过 URL http://localhost:8080/personne/main 访问。在该 URL 下,会显示由页面 formulaire.personne.jsp 提供的表单:

用户填写表单后,点击提交按钮 [Envoyer]。重置按钮 [Rétablir] 用于将文档恢复至接收时的初始状态。 按钮 [Effacer] 属于普通按钮类型。用户必须提供有效的姓名和年龄。若未满足此条件,系统将通过页面 JSP erreurs.personne.jsp 向用户发送错误页面。以下为示例:
交互示例 1
![]() | ![]() |
如果点击链接 [Retour au formulaire],会发现该页面仍保持着我们离开时的状态:
第2次交换
![]() | ![]() |
如果用户发送了正确的数据,应用程序将通过页面 JSP reponse.personne.jsp 向其发送响应。
交换 1
![]() | ![]() |
如果点击链接 [Retour au formulaire],会发现它仍处于我们离开时的状态:
第2次交换
![]() | ![]() |
2.2. 应用程序的 Struts 架构
我们将采用以下 Struts 架构:
![]() |
- 将包含三个视图
- 控制器将采用Struts提供的控制器
- FormulaireBean 是负责存储由视图 formulaire.personne.jsp 呈现的表单值的类
- FormulaireAction 是负责处理 FormulaireBean 的值并指定要发送的响应页面的类:
- 若表单数据有误,则返回视图 erreurs.personne.jsp
- 否则,则返回视图 reponse.personne.jsp
对于开发人员而言,工作内容是编写以下代码:
- 三个视图
- 与表单关联的 FormulaireBean Bean
- 负责处理表单的 FormulaireAction 类
2.3. 编译 Struts 应用程序所需的类
为了编译我们应用程序所需的类,我们将使用JBuilder。该工具使用的是JDK,其中并不包含Struts应用程序所需的类。我们可以按以下方式配置JBuilder:
- 选项 Tools(工具)/Configure JDKs(配置 JDK)

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

可以将上述所有 .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 应用程序的视图
该应用程序的三个视图如下:
- formulaire.personne.jsp:显示用于输入个人姓名和年龄的表单
- reponse.personne.jsp:若输入值有效,则显示这些值
- erreurs.personne.jsp:若存在错误,则显示错误信息
2.4.1. 视图 erreurs.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>
该代码中有两处新内容:
- 出现了 <html:XX/> 标签,而这些并非 HTML 标签。 实际上,我们可以创建 JSP 标签库,当将页面 JSP 转换为 Servlet 时,这些标签会被转换为 Java 代码。
- JSP页面必须声明其使用的标签库。此处通过以下代码行进行声明
该行提供了两项信息:
- uri:管理库使用规则的文件位置。文件 struts-html.tld 包含在 Struts 发行版中。在上例中,该文件将放置在 WEB-INF 文件夹内。
- prefix:代码中用于为库标签添加前缀的标识符。这有助于避免在同时使用多个标签库时可能出现的命名冲突。不同库中可能存在同名的标签。通过为每个库指定不同的前缀,可以消除所有歧义。
- <html:errors> 标签用于显示 Struts 控制器传递给它的错误列表。
- <html:link> 标签生成一个指向 /C/page 的链接,其中
- C 是应用程序的上下文
- page 是标签 page 属性中指定的 URL
标签
标签将生成以下代码 HTML:
其中 C 是应用程序的上下文
2.4.2. 视图测试 erreurs.personne.jsp
- 文件 erreurs.personne.jsp 位于 strutspersonne 应用程序的 views 文件夹中:

- 文件 struts-html.tld 取自 Struts 发行版(<struts>/lib),并放置在 WEB-INF 中:

- 文件 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 /erreurs.do 将被重定向到视图 /vues/erreurs.personne.jsp。 文件 struts-config.xml 被放置在文件夹 WEB-INF 中。
- 我们重启 Tomcat 以使新文件 struts-config.xml 生效,然后访问网址 http://localhost:8080/strutspersonne/erreurs.do:

<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. 视图 reponse.personne.jsp
该视图用于确认表单中输入的值,如下所示:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%
// 获取姓名、年龄数据
//String 姓名 = (String)request.getAttribute("姓名");
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>
该页面显示两条信息 [nom] 和 [age],这些信息将由控制器通过预定义的 request 对象传递给它。 在此,我们进行一项测试,其中控制器将无法设置 [nom] 和 [age] 的值。因此,我们使用任意值初始化这两个信息。此外,此处的表单返回链接也是由 <html:link> 标签生成的。
2.4.4. 测试视图 reponse.personne.jsp
- 文件 reponse.personne.jsp 位于 strutspersonne 应用程序的 views 文件夹中:

- 文件 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.jsp。 文件 struts-config.xml 被放置在文件夹 WEB-INF 中。
- 我们重启 Tomcat 以使新文件 struts-config.xml 生效,然后访问网址 http://localhost:8080/strutspersonne/erreurs.do:

结果与预期一致。
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>,也用于向负责处理此表单的控制器提供信息:
需要注意的是,将表单参数(GET/POST)发送至控制器的方法并未明确指定。 可以通过 method 属性来指定。如果未指定该属性,则默认使用方法 POST。 | |||||||
用于生成 <input type="text" value="..."> 标签:
| |||||||
用于生成 HTML <input type="submit"...> 标签 | |||||||
用于生成标签 HTML <input type="reset"...> | |||||||
用于生成标签 HTML <input type="button"...> |
2.4.6. 与表单关联的 Bean formulaire.personne.jsp
- 在 Struts 中,每个表单都必须关联一个 Bean,该 Bean 负责存储表单的值并将其保存在当前会话中。Bean 是一个必须遵循特定语法的 Java 类。与表单关联的 Bean 必须继承 Struts 库中定义的 ActionForm 类:
- Bean 的属性名称必须与表单字段(即表单中 html:text 标签的 property 属性)相对应。根据前面的表单代码,该 Bean 必须包含两个名为 nom 和 age 的字段。
- 对于表单中的每个字段 XX,Bean 必须定义两个方法:
- public void setXX(Type 值):用于将值赋给属性 XX
- public void getXX():用于获取字段 XX 的值
与上述表单关联的 Bean 可能如下所示:
package istia.st.struts.personne;
import org.apache.struts.action.ActionForm;
public class FormulaireBean extends ActionForm {
// 姓名
private String nom = null;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
// 年龄
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 文件夹中:

- 文件 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 /表单,供 Struts 控制器处理。 URL /formulaire.do 将被重定向到视图 /vues/formulaire.personne.jsp。 文件 struts-config.xml 被放置在文件夹 WEB-INF 中。
- 我们将类 FormulaireBean 放置在 WEB-INF/classes 中:

- 我们重启 Tomcat 以便新文件 struts-config.xml 生效,然后访问网址 http://localhost:8080/strutspersonne/formulaire.do:

我们成功获取了表单。出于好奇,我们可以查看散布在表单代码 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>
在生成的表单中,[恢复] 和 [Effacer] 按钮均可正常使用。提交按钮 [Envoyer] 跳转至 URL /strutspersonne/main.do。 根据应用程序中的 web.xml 文件,Struts 控制器将处理该请求。根据 struts-config.html 文件,控制器应将请求重定向至 /vues/main.html 视图。让我们试一试:

一切如预期进行。接下来我们需要真正处理表单的值,即 c.a.d。编写一个 Action 类型的类,该类将接收表单数据并将其存储在 FormulaireBean 对象中。








