9. Web 应用程序 MVC [personne] – 版本 4
此版本使用了前文介绍的 JSTL 标签库。
9.1. Eclipse 项目
要创建 Web 应用程序 [/personne4] 的 Eclipse 项目 [mvc-personne-04],需按照第 78 页第 6.2 节所述步骤复制项目 [mvc-personne-03]。
![]() | ![]() |
9.2. Web 应用程序 [personne4] 的配置
应用程序 /personne4 的文件 web.xml 如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>mvc-personne-04</display-name>
...
该文件与上一版本完全相同,仅第 6 行有所变化,其中 Web 应用程序的显示名称已更改为 [mvc-personne-04]。
[index.jsp] 主页发生如下变化:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<c:redirect url="/main"/>
- 第 5 行:页面 [index.jsp] 将客户端重定向至 URL [/main],该 URL 指向应用程序 [/personne4] 的控制器 [ServletPersonne]。 <c:redirect> 标签属于 JSTL / Core 库。其特点在于通过添加以下内容来补充其 [url] 属性的 URL:
- 前缀 [/contexte],其中 [contexte] 是应用程序的上下文,此处为 [personne4]。
- 后缀 [?jsessionid=id_session](如果发起请求的浏览器未发送会话 Cookie)。标识符 [jsessionid] 表示 Web 服务器发送给客户端的会话令牌标识符。它取决于 Web 服务器。 此处为 Tomcat 服务器的标识符。[id_session] 即会话令牌本身。
因此,第5行中[index.jsp]的真实重定向URL是[/personne4/main?jsessionid=XX],其中XX是会话令牌。 下图即为初始请求 URL [http://localhost:8080/personne4] 后所显示的页面:

<c:redirect>标签与会话令牌之间的关联相当微妙。现在探讨这个问题为时尚早,但我们日后会有机会再回来讨论。
9.3. 视图代码
9.3.1. 视图 [formulaire]
该视图未发生变化:

它由以下页面生成:JSP [formulaire.jsp]
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne - formulaire</title>
<script language="javascript">
...
</script>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="${nom}" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="${age}" type="text" size="3"></td>
</tr>
<tr>
</table>
<table>
<tr>
<td><input type="submit" value="Submit"></td>
<td><input type="button" value="[Envoyer]" onclick="envoyer()"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="[Effacer]" onclick="effacer()"></td>
</tr>
</table>
<input type="hidden" name="action" value="validationFormulaire">
</form>
</center>
</body>
</html>
新增内容:
- 第4行:声明JSTL / Core标签库
- 第21、25行:在页面模板中获取[nom, age]属性。 需要提醒的是,这些属性将依次在页面 JSP 的请求 [request]、会话 [session] 以及应用程序 [application] 中进行查找。 在本例中,控制器将把它们放入会话中。
- 由于上述操作,页面 JSP 的开头不再包含用于获取页面模板的 Java 代码。
9.3.2. 视图 [reponse]
该视图未发生变化:
![]() | ![]() |
新页面 JSP [reponse.jsp] 如下所示:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Personne - réponse</h2>
<hr>
<table>
<tr>
<td>Nom</td>
<td>${nom}</td>
</tr>
<tr>
<td>Age</td>
<td>${age}</td>
</tr>
</table>
<br>
<form name="frmPersonne" method="post">
<input type="hidden" name="action" value="retourFormulaire">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
新增内容:
- 第4行:声明JSTL / Core标签库
- 第16、20、28行:在页面模板中获取[nom, age, lienRetourFormulaire]属性。页面开头不再包含用于获取该属性的Java代码JSP。
9.3.3. 视图 [erreurs]
该视图未发生变化:
![]() | ![]() |
新页面 JSP [erreurs.jsp] 如下所示:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
<c:forEach var="erreur" items="${erreurs}">
<li>${erreur}</li>
</c:forEach>
</ul>
<br>
<form name="frmPersonne" method="post">
<input type="hidden" name="action" value="retourFormulaire">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
新增内容:
- 第4行:声明JSTL / Core标签库
- 第13-15行:使用JSTL显示错误列表
- 页面开头不再包含用于获取页面模板的 Java 代码 JSP。
9.4. 视图测试
为了对上述视图进行测试,我们将它们的页面 JSP 复制到 Eclipse 项目的 /WebContent/JSP 文件夹中:

然后在 JSP 文件夹中,对页面进行如下修改:
[formulaire.jsp]:
...
<%
// -- 测试:创建页面模板
session.setAttribute("nom","tintin");
session.setAttribute("age","30");
%>
<html>
<head>
已添加第 4-5 行以创建页面所需的模板。
[reponse.jsp]:
...
<%
// -- 测试:创建页面模板
request.setAttribute("nom","milou");
request.setAttribute("age","10");
request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>
<html>
<head>
...
已添加第 4-6 行以创建页面所需的模板。
[erreurs.jsp]:
<%
// -- 测试:创建页面模板
ArrayList<String> erreurs1=new ArrayList<String>();
erreurs1.add("erreur1");
erreurs1.add("erreur2");
request.setAttribute("erreurs",erreurs1);
request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>
<html>
<head>
已添加第 4-8 行以创建页面所需的模板。
如果尚未运行,请启动 Tomcat,然后请求以下 URL:
![]() | ![]() |
![]() |
我们确实获得了预期的视图。
9.5. 控制器 [ServletPersonne]
Web 应用程序 [/personne3] 中的控制器 [ServletPersonne] 将处理以下操作:
编号 | 请求 | 来源 | 处理 |
1 | [GET /personne4/main] | 用户输入的URL | - 发送空的视图 [formulaire] |
2 | [POST /personne4/main] 带参数 [txtNom, txtAge, action=validationFormulaire] 已发布 | 点击按钮 [Envoyer] 视图中的 [formulaire] | - 检查参数值 [txtNom, txtAge] - 若参数值不正确,则发送视图 [erreurs(erreurs)] - 若参数正确,则发送视图 [reponse(nom,age)] |
3 | [POST /personne4/main] 带参数 [action=retourFormulaire] 已发布 | 点击链接 [返回 表单] 链接 [réponse] 和 [erreurs]。 | - 发送已预填入最新输入值的视图 [formulaire] |
控制器 [ServletPersonne] 的框架与上一版本完全相同。我们将重点审查对方法 [doInit, doValidationFormulaire, doRetourFormulaire] 所做的修改,而方法 [init, doGet, doPost] 保持不变。
9.5.1. 方法 [doInit]
该方法处理第 1 号请求 [GET /personne4/main]。其代码如下:
新增内容:
- 第3行:显示视图[formulaire]。该视图在其模板中期待“name”和“age”这两个属性。但它无法找到这些属性,因为控制器并未将它们传递进去。 在这种情况下,库 JSTL 将为这些属性获取 null 的指针。 这不会引发错误,视图 [formulaire] 中的 ${nom} 和 ${age} 元素将显示为空值。这正是我们所期望的。 这样,我们就无需初始化视图 [formulaire] 的模型。
9.5.2. 方法 [doValidationFormulaire]
该方法处理第 2 号请求 [POST /personne4/main],其提交数据中包含 [action, txtNom, txtAge]。其代码如下:
更新内容:
- 第 15 行:方法 [doValidationFormulaire] 返回视图 [réponse]。该视图的模板中包含元素 [nom, age, lienRetourFormulaire]。 [lienRetourFormulaire] 通过请求在第 14 行被放入模板中。 而 [nom,age] 元素则是通过会话,在第 8-10 行放入模型中的。在之前的版本中,当发送 [réponse] 视图时,我们也将 [nom, age] 元素放入了请求中,因为该视图正是在那里等待这些元素的。 在此,借助 JSTL 库,我们知道系统将遍历不同上下文(请求、会话、应用程序)以查找模型中的元素。因此,这些元素将在会话中被找到,因为控制器已将其放入会话中(第 8-10 行)。
9.5.3. 方法 [doRetourFormulaire]
该方法处理第3号请求 [POST /personne4/main],其提交数据中包含 [action=retourFormulaire]。其代码如下:
更新内容:
- 第 4 行:显示视图 [formulaire]。该视图在其模型中等待“姓名”和“年龄”属性。 它将在会话中找到这些属性,因为方法 [doValidationFormulaire] 已将其放入会话中,且该方法必然在方法 [doRetourFormulaire] 之前执行。因此,在第 4 行显示 [formulaire] 之前,无需初始化其模型。 因此,方法 [doInit] 和 [doRetourFormulaire] 完全相同,我们可以删除操作 [retourFormulaire],并用操作 [init] 代替。 届时,方法 [doRetourFormulaire] 将被移除。
9.6. 测试
在此新版本中,仅视图发生了变化。控制器 [ServletPersonne] 本身并未改变。使用 JSTL 仅仅是为了让我们能够在 JSP 页面中更简便地利用控制器构建的模型。
将Eclipse项目[personne-mvc-04]集成到Tomcat后,启动或重启Tomcat。访问网址[http://localhost:8080/personne4]。








