走上开放之路:ASP开发人员的J2EE基础(下)

相关文章:走上开放之路: ASP 开发人员的 J2EE 基础(上)

ASP/COM 和 J2EE 应用程序模型

接下来研究不同的应用程序体系结构,您可以使用这些体系结构开发 J2EE 应用程序并将 其与相应的 ASP/COM 应用程序体系结构关联起来。

使用 Java Servlets 编程:基础知识

编写 Java Servlets 就可以对来自 URL 的请求进行可编程控制。典型的 servlet 调用 类似于以下步骤:

客户机向 Web 服务器发出请求,将 servlet 命名为 URL 的一部分 —— 例如, 。

Web 服务器将该请求转发给应用程序服务器,该服务器查找 servlet 类的实例。

Web 容器调用 servlet。(servlet 的一个实例被加载到内存中,每个请求都调用不同线 程上的一个实例。)

注意,HTML 表单中 servlet 的 URL 包括 servlet 的名字和称为 上下文根(在上例中 是 /myWebApp )的前缀。上下文根大致等价于 IIS 虚拟目录。

图 2 说明了这些步骤。

图 2. Servlet 调用

Servlets 扩展 HttpServlet 类。如有需要,可以覆盖 下列 HttpServlet 类的方法:

init() :在应用程序服务器加载 servlet 时调用

destroy() :在应用程序服务器卸载 servlet 时调用

doGet() :通过 HTTP GET 调用 servlet 时调用

doPost() :通过 HTTP POST 调用 servlet 时调用

编写 servlet 涉及编写代码来处理 HTTP 请求,处理任何参数并直接返回任何内容,或 委派另一种资源(如 JSP 页面)来处理响应。不建议直接从 servlet 返回 HTML,因为管理 Java 类内的 HTML 代码很不灵活。

当应用程序服务器调用 doGet() 或 doPost() 方法时,以下两个对象将作为参数传递进 来:

HttpServletRequest 允许访问任何请求参数以及 HTTP 请求中引发 servlet 调用的其他 信息。

HttpServletResponse 充当返回到客户机的沟通渠道,允许 servlet 直接返回内容或返 回其他 HTTP 返回代码(错误、重定向等)。

清单 20 和 21 展示了两个 Hello World servlet。清单 20 直接返回内容,清单 21 使 用 JSP 页面返回内容。

清单 20. HelloWorld servlet:直接返回内容

public class HelloWorldServlet extends HttpServlet {/**  * Handles all HTTP POST requests  *  * @param request Object that encapsulates the request to the servlet  * @param response Object that encapsulates the response from the servlet  */public void doPost(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response)throws ServletException, IOException {try {  PrintWriter ut = response.getWriter();  out.println("");  out.println("Hello World");  out.println("");} catch (Throwable t) {  ...}}}

注意,您从响应对象获得 PrintWriter ,并一次一行将 HTML 输出到客户机。

清单 21. HelloWorld servlet:使用 JSP 页面返回内容

public class HelloWorldServlet extends HttpServlet {/**  * Handles all HTTP POST requests  *  * @param request Object that encapsulates the request to the servlet  * @param response Object that encapsulates the response from the servlet  */public void doPost(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response)throws ServletException, IOException {try {       RequestDispatcher rd = getServletContext().getRequestDispatcher ("helloworld.jsp");       rd.forward(request, response);} catch (Throwable t) {  ...}}}

RequestDispatcher 是您希望将请求转发给的资源的包装器。注意,要同时包括原始请求 和响应对象,以便目标资源可以访问它们。从 getServletContext() 返回的 ServletContext 允许服务器与底层应用程序进行通信来获得 RequestDispatcher 。注意, 所有 servlet 都通过 etServletContext() 方法访问其 ServletContext 。

使用 JSP 技术编程:基础知识

使用 JSP 技术您就具有使用 Java 语言编写服务器端脚本的能力。在 JSP 页面返回到客 户机前,它是一个组合页面,由 HTML 和应用程序服务器处理的 Java 代码组成。在页面返 回到客户机前,应用程序服务器处理嵌入代码以生成静态内容。与 .aspx 文件类似,JSP 页 面通常与 HTML 文件很相似,只是增加了一些额外的标签和 Java 代码片断。

在第一次请求 JSP 页面时,应用程序服务器将每个 JSP 页面转换为特殊的 servlet。该 servlet 编译并加载到内存中。只要 JSP 源未被修改,这个 servlet 就对要获得该页面的 请求提供服务。在源修改后,此过程再次开始,并生成一个新版本的 servlet。

您可以在 JSP 页面中使用几种特殊的 JSP 标签,用户还可以定义自己开发的标签的行为 。您还可以将大段的 Java 代码添加到页面的不同部分。J2EE 运行时环境创建了许多变量, 称为 隐含变量—— 可用于这些 Java 代码的片断。隐含变量的例子有:

request:与页面的特定调用相关的 HttpServletRequest

response:与页面的特定调用相关的 HttpServletResponse

out:与 HttpServletResponse 相关的 PrintWriter

清单 22 展示了 JSP 页面的一个例子,该页面既包含 HTML 也包含 Java.代码。 标签之间的 Java 代码部分称为 scriptlet。

清单 22. HelloWorld servlet:使用 JSP 页面返回内容

JSP page exampleThe date is:Some more HTMLThe value of e is:Yet even more HTMLThe value of PI is:

注意,JSP 隐含变量 out 的用途是将内容写回到客户机,还要注意 HTML 和 Java 代码 的交织。

一个示例场景

为了说明各种体系结构选项,我们将使用一个简单的用户登录场景,它包含:

一个具有 HTML 表单的登录页面,它从用户那里获得用户名和密码

验证用户凭证(可能使用数据库)并重定向站点主页的应用逻辑

使用这个简单的例子可以说明各种应用程序体系结构。

“意大利面条式”代码

在 ASP 端,“意大利面条式”代码方法使用单个 .aspx 文件来同时包含应用逻辑和 HTML 表单。(不建议对现实中的例子采用这种方法,因为这样所有表示逻辑和应用逻辑都将 是单个文件,从而您就不能重用用于验证用户凭证的代码。)该代码的轮廓看起来类似清单 23 中所示的代码。(为简单起见,我们省略了所有错误处理代码。)

清单 23. ASP 中的“意大利面条式”代码

'--FUNCTION TO VALIDATE USER ENTERED LOGIN DATA FUNCTION ValidateUser (username,password)  '--Code to validate users credentials goes here  ...END FUNCTION %>Login example       

正如清单 24 所示,您可以在 J2EE 中采用相同的方法,使用单个 JSP 页面来同时包含 表单和应用逻辑。

清单 24.J2EE 中的“意大利面条式”代码

Login example...      </form. 

与 ASP 模型类似,JSP 模型不是事件驱动的,因此您需要检查表单是否被发送回去了, 方法是检查该请求,并且如果不是 POST 请求时则添加表单的 HTML。如果它是 POST 请求, 您将使用在 JSP 中声明的一个方法来验证登录。注意,使用 <%! 表明该代码是一个方法 。Scriptlet 代码将在 JSP 页面处理期间遇到它们的时候执行,因此用于 scriptlet 的标 签( )对方法无效。还要注意如何使用 if/then/else 编程结构来方便地添加 或去除较大的 HTML 块。与在 ASP 例子中一样,不推荐将此方法用于 J2EE 开发。表示代码 (HTML)和应用逻辑的混合仅允许很少的重用,并且使得代码难于维护。

改进的“意大利面条式”代码

在 ASP 端,可以以前一个例子为基础建立一种更好的方法,不过除了 login.asp 文件外 ,还使用只包含验证逻辑的一个 include ASP 文件。这样您就可以重用其他 ASP 文件中的 代码。

J2EE 端的一种更好方法是将应用逻辑转移到一个 Java Servlet,从而使 JSP 页面仅限 于使用 HTML 组件。现在验证逻辑独立于显示表单的页面,这是一种改进,而 JSP 页面仅限 于使用 HTML 组件也是一种改进。清单 25 显示了如何将应用逻辑放到 servlet 中从而简化 JSP 页面。

清单 25. J2EE:JSP 页面中改进的“意大利面条式”代码

Login example...

清单 26 显示了 servlet 中的验证代码和导航逻辑。

清单 26. J2EE:Java Servlet 中改进的“意大利面条式”代码

public class LoginServlet extends HttpServlet {/**  * Handles all HTTP POST requests  *  * @param request Object that encapsulates the request to the servlet  * @param response Object that encapsulates the response from the servlet  */public void doPost(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response)throws ServletException, IOException {try {      String userName = request.getParameter("username");      String password = request.getParameter("password");      if (validateUser(userName, password)) {       response.sendRedirect("mainpage.jsp");      }       ...} catch (Throwable t) {  ...}}private boolean validateUser(String userName, String password) {    ...   }}

清单 26 中的 servlet 是表单提交的目标,并且充当一个控制器——处理用户输入并基 于该输入调出适当的页面。注意 HttpServlet 父类允许您通过提供可重载的方法( doGet() 和 doPost() )来同时处理 GET 和 POST 请求。

这种方法的主要缺点在于,凭证验证代码(它很可能要访问数据库)是 J2EE 例子中 servlet 的一部分。如果不同的页面需要使用这个逻辑,您就必须重复它。重复的代码更难 于维护和更易于出错,因为您必须跟踪多个副本。

模型-视图-控制器(MVC)方法

下面我们将展示如何对这个例子使用更纯的 MVC 方法。在 ASP 端,这体现为将凭证验证 逻辑转移到一个单独 COM 组件,然后您在 ASP 文件中进行访问。在 J2EE 端,凭证验证代 码将转移到一个单独的类中,然后从 servlet 访问该类。清单 27 中的代码片断显示了该 servlet 的外观。

清单 27. J2EE: Java Servlet 中的 MVC

import com.ibm.businessobjects.UserValidationpublic class LoginServlet extends HttpServlet {/**  * Handles all HTTP POST requests  *  * @param request Object that encapsulates the request to the servlet  * @param response Object that encapsulates the response from the servlet  */public void doPost(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response)throws ServletException, IOException {try {      String userName = request.getParameter("username");      String password = request.getParameter("password");      UserValidation user = new UserValidation();      if (user.validate(userName, password)) {       response.sendRedirect("mainpage.jsp");      }       ...} catch (Throwable t) {  ...}}}

清单 28 显示了位于一个单独的类中的凭证验证代码。

清单 28. J2EE:用户验证类中的 MVC

package com.ibm.businessobjects;public class UserValidation {  public boolean validate(String username, String password) {   ...  }}

凭证验证在 servlet 使用的类中进行。现在该 servlet 不必直接了解验证如何进行。只 要您保持相同的公共接口不变,就可以随意更改 UserValidation 而不需改变 servlet 代码 。您还可以在非 Web 应用程序中重用该代码。

其他 J2EE 组件

前面的例子展示了如何将业务逻辑分离到一个或一组单独的类中。这样允许您以各种不同 的方式实现业务逻辑,而不会影响 servlet 和 JSP 页面。与使用一个需要访问数据库(使 用 JDBC)的业务对象不同,您可以通过各种不同的方式实现这个逻辑。例如:

使用 JCA 来访问诸如大型机等遗留系统:JCA 是一个 J2EE API,它允许 J2EE 应用程序 使用标准接口与遗留系统(比如 CICS 或者 IMS)交互。

使用 Web 服务客户端 API 来访问 Web 服务:这种方法涉及使用 Apache Axis 或其他某 种 Java Web 服务客户端 API 来访问 Web 服务。

使用 JMS 将消息作为验证请求来发送:这种方法涉及使用标准 API 来访问 JMS 相容的 消息中间件(比如 WebSphere MQ)。

使用 EJB 技术来实现验证逻辑:这种方法涉及使用 EJB 组件(而不是简单的 Java 类) 来实现业务逻辑。EJB 组件能够使用应用服务器中的服务来管理(数据库或其他)事务,管 理方法级的安全,以及提供群集和高速缓存。将此类任务委托给应用服务器,您可以把精力 集中在业务逻辑上,而不必担心系统级的问题。

J2EE 数据访问

下面我们将介绍 JDBC API,这是 J2EE 下的行业标准接口集,它允许 Java 程序使用统 一的 API 调用集来访问关系数据库。JDBC 允许您开发应用程序一次,然后针对任何 JDBC 相容的数据库部署它们 —— DB2、Oracle、SQL Server、Sybase、mySQL、Informix 以及其 他数据库。

JDBC API 允许任何 Java 组件(包括 Java Servlets 和 JSP 页面)无缝地访问关系数 据库中的数据。JDBC 由两部分组成:用于访问数据库的 API,以及数据库厂商为各自的数据 库提供的可嵌入 JDBC 驱动程序。JDBC API 最便利的特性之一在于,您不必使用任何特定于 厂商的类。您可以在运行时使用一个字符串常量来指定适当的驱动程序,以后就可以使用相 同的编程接口,而不管所使用的是哪种数据库。这样您就可以切换数据库,而不必更改代码 (只要您在运行时提供字符串常量以指定驱动程序)。

一个 JDBC 例子

典型的 JDBC 应用程序必须完成以下步骤才能与数据库交互:

识别驱动程序。(每个应用程序只需执行这个步骤一次。)

识别数据库并与之建立连接(在需要时提供身份验证信息)。

执行查询和/或更新。

处理结果。

断开与数据库的连接。

清单 29 说明了上述步骤。

清单 29. 一个 JDBC 例子

// Step 1. SPECIFY THE APPROPRIATE DRIVER TO USEClass.forName("COM.ibm.db2.jdbc.app.DB2Driver");// Step 2. Identify the database and connect to itConnection conn = DriverManager.getConnection ("jdbc:db2:SAMPLE","userid","password");// Step 3. Execute queryStatement stmt = conn.createStatement();stmt.execute("SELECT * FROM USERID.EMPLOYEE");// Step 4. Get the resultsResultSet rs = stmt.getResultSet();while (rs.next()) {  String firstCol = rs.getString(1);  int secondCol  = rs.getInt(2);  ...}// Step 5. Disconnect from the databaseconn.close();

清单 29 中的 Step 1 动态地加载适当的驱动程序。这个例子使用的是 DB2;其他 JDBC 驱动程序具有不同的完全限定名称。Step 2 提供特定于驱动程序的 String 指出要连接到哪 个数据库。每种 JDBC 驱动程序都有自己的 String 格式。DB2 使用的格式是 “jdbc:db2:DBNAME” ,因此在此例中系统要连接到一个名为 SAMPLE 的数据库。例子中还提 供了身份验证信息,以便数据库服务器能够对连接请求进行身份验证。在 Step 4 中,注意 例子中如何循环遍历结果集,直到 next() 方法返回 false 。您还必须知道每列的类型,并 对每列和每种类型调用适当的 getXXXX(n) 方法。还要注意您传递给 getXXXX(n) 方法的整 数是列编号。

在 ASP 页面使用 ADO 但没有连接池时,以上方法与典型的 ASP 页面采用的方法很相似 ,因为程序员负责打开和关闭数据库连接。

连接池

连接池通过对可以同时打开的数据库连接数目规定上限,可以增加应用程序的可伸缩性, 因而防止由于过多的连接请求而造成数据库服务器的过度运行。对于 ASP 来说,如果您选择 的数据库(如 DB2、SQL Server 或 Oracle)有 OLEDB 提供程序,则可以利用连接池,从而 就不必直接管理数据库连接。

有了 JDBC,您可以将自己从直接管理连接的工作中解放出来。J2EE 应用程序服务器被要 求为它们支持的所有数据库提供连接池。它们不使用某些高级的 JDBC API 调用来完成该任 务。当您的代码在应用程序服务器的监控下运行时,您就不必直接与数据库服务器交互,以 便为每个配置的数据库维护连接池。然后,应用程序从该池中请求连接,并在使用完这些连 接之后,将其返回到该池。大多数应用程序服务器都有相当高级的选项对池进行管理,包括 “收回”连接的能力,即从出错的应用程序(没有在给定时间内将连接返回池中)取回连接 。

使用连接池的应用程序的典型流程如下:

查找应用服务器资源库中的 DataSource (用于访问特定的连接池)。(每个应用服务器 都有一个资源库,其中包含所有已配置的连接和其他资源,比如消息队列和 SMTP 提供程序 。您可以使用名为 JNDI 的标准 J2EE API 来访问资源库。)(这个步骤只需执行一次。)

从池中获得连接(在需要时提供身份验证信息)。

执行查询和/或更新。

处理结果。

将连接返回池中。

清单 30 展示了使用连接池的一个例子。

清单 30. 一个连接池例子

// Step 1. Look up the DataSourceInitialContext ic = new InitialContext();DataSource ds = (DataSource) ic.lookup("jdbc/MyDS");// Step 2. Get a connection from the poolConnection conn = ds.getConnection();// Step 3. Execute queryStatement stmt = conn.createStatement();stmt.execute("SELECT * FROM USERID.EMPLOYEE");// Step 4. Get the resultsResultSet rs = stmt.getResultSet();while (rs.next()) {  String firstCol = rs.getString(1);  int secondCol  = rs.getInt(2);  ...}// Step 5. Return connection to the poolconn.close();

Step 1 假设应用服务器已经配置了名为 “jdbc/MyDS” 的 DataSource 。这样就封装了一 个特定的 JDBC 驱动程序和数据库。您还可以向 DataSource 定义添加身份验证信息,这样 应用程序就不必提供该信息。您可以使用 InitialContext 类(它是 JNDI API 的一部分) 来查找应用服务器控制的各种资源。Step 3 至 Step 5 与前一个例子相同,不过要注意 Step 5 中对 close() 方法的调用仅把连接返回池中,而不是关闭该数据库连接。

J2EE 应用程序状态管理

在编写 J2EE Web 应用程序时,要管理应用程序的状态,有一组丰富的类和接口可供选择 。我们将介绍这些类和接口,并讨论如何在 Java Servlets 和 JSP 页面中使用这些类和接 口。不过,我们将首先介绍 范围的概念,它是理解 J2EE 中的应用程序状态管理的关键。

范围

从程序员的角度看,状态管理涉及临时存储数据和在需要时检索它们。在 J2EE 中,您可 以选择多个“存储位置”,每个位置具有它自己规则,这些规则控制任何存储的数据得有效 时间。持续时间从处理某个特定页面所需的时间(临时存储一些数据),到应用程序运行生 命期(长期存储数据)不等。J2EE 中的“存储位置”选择称为特定存储请求或检索的 范围 。该范围决定了您将把数据附加到哪些 J2EE 对象,以及那些数据将在多长时间内可用。可 用的范围是:

会话:这类似于 ASP 中的会话范围。只要会话还是活动的,您就可以在该用户会话范围 内放置任何 Java 对象并检索它。J2EE 应用程序使用 HttpSession 接口(类似于 ASP 中的 SESSION )。可以使用 String 作为标签将对象添加到会话中,并使用相同的标签来检索它 。

请求:在 J2EE 中,HttpServletRequest 对象允许您向它附加数据,这非常类似 HttpSession interface 接口。当多个资源处理单个请求时,这是很有用的。例如,某个 Java Servlet 可能是一个 HTML 表单提交的目标,然后它将请求转发给一个 JSP 页面以完 成它。在这个例子中,该 sevlet 能够向 HttpRequest 对象附加数据,并且 JSP 页面能够 访问它。注意在这种场景中,该 servlet 和 JSP 页面都使用相同的 HttpRequest 对象。

应用程序:所有 J2EE Web 应用程序在部署之前都打包到一个具有 .war 扩展名的文件中 。该文件的格式是标准的,因此您可以把同一个应用程序部署到不同的应用服务器。单个 .war 文件中的所有 J2EE 组件都被认为是同一个应用程序的组成部分,并且共享共同的应用 程序上下文。这是通过 ServletContext 接口向开发人员公开的,这个接口(就像 HttpSession 和 HttpRequest 口一样)允许您附加和删除任何 Java 对象。只要应用程序还 在运行,添加到 ServletContext 的项就可用,并且会在单独会话的创建和销毁过程中保留 下来。这类似于 ASP 中的 APPLICATION 对象。

页面:页面上下文在处理单个页面的过程中可用。如,JSP 页面顶部的 Java scriptlet 能够在 PageContext 中放置对象,然后相同页面中的其他 scriptlet 就可以访问它。

管理应用程序状态

现在您已经对范围有了更好的了解,下面我们可以深入地讨论管理 J2EE Web 应用程序中 的状态的机制。最佳实践是,对于任何临时的状态存储,您都应该确定需要存储该数据多长 时间,然后使用满足需要的、具有最短生存时间的范围。例如,假设您需要某个 JSP 页面中 的数据,该 JSP 页面是从某个 servlet 转发的请求的目标。虽然会话状态和应用程序状态 也满足您的需要,但是在这两种情况下,数据都会在使用完之后悬置在那里。这样不必要地 增加了当前应用程序的资源需求。对于这个例子,请求范围能够满足需要,却不会在您不需 要之后还将数据悬置在那里。

管理 JSP 页面中的状态

在 JSP 脚本环境中,所有范围对象都是用隐含变量来表示的。您可以在自己的 sciptlet 中使用这些变量,而不需要显式地声明它们。可以使用的隐含变量有:

session: 实现 HttpSession 接口的类的一个实例。

application:实现 HttpSession 接口的类的一个实例。

request:实现 HttpServletRequest 接口的类的一个实例。

pageContext: PageContext 类的一个实例。

清单 31 展示了如何在 JSP scriptlet 中针对不同的范围添加和删除对象。

清单 31. JSP 页面中的状态管理

....

清单 31 中的例子的第一行是 page 指令,它允许您定义整个页面的属性。请注意 session 属性的使用,它决定了该页面是否要使得会话可用。如果将它设置为 true 却还没 有建立会话,那么新的会话就会为您创建。如果将它设置为 false,那么会话范围将在该 JSP 页面中不可用。(这个属性的面默认设置是 true,因此这里使用它是多余的,只是出于 说明目的。)

清单 32 是使用各种可用范围来存储和检索数据的 servlet 的一个例子。

清单 32. servlet 中的状态管理

public class MyServlet extends HttpServlet {  public void doGet(    HttpServletRequest request, HttpServletResponse response)    throws ServletException, IOException {    performTask(request, response);  }  public void doPost(HttpServletRequest request, HttpServletResponse response)    throws ServletException, IOException {    performTask(request, response);  }  /**   * Handles all HTTP GET and POST requests   *   * @param request Object that encapsulates the request to the servlet   * @param response Object that encapsulates the response from the servlet   */  public void performTask(    javax.servlet.http.HttpServletRequest req,    javax.servlet.http.HttpServletResponse res)    throws ServletException, IOException {    try {      // This is how you create a session if is has not been created yet      // Note that this will return the existing session if you've      // already created it       HttpSession session = req.getSession();     //This is how the application context is retrieved in a servlet     ServletContext application = getServletContext();       String foo = "I am a Foo";       session.setAttribute("Foo", foo);     // Place object in session scopesession.setAttribute("Foo", foo);    // Retrieve from session scopeString sessionFoo = (String) session.getAttribute("Foo");    // Place object in application scopeapplication.setAttribute("Foo", foo);    // Retrieve from application scopeString applicationFoo = (String) application.getAttribute("Foo");    // Place object in request scoperequest.setAttribute("Foo", foo);   // Retrieve from request scope  String requestFoo = (String) request.getAttribute("Foo");       ...    } catch (Throwable t) {     // All errors go to error page     throw new ServletException(t.getMessage());    }  }

JSP 页面和 sevlet 中的会话之间的区别在于,在 sevlet 中,您必须显式地创建和检索 它,而在 JSP 页面中,这是自动为您完成的。注意 pageContext 仅适用于 JSP 页面,而不 适用于 servlet;还要注意 servlet API 如何提供了两个要覆盖的方法来处理 GET 和 POST HTTP 请求。这个例子提供了一个名为 performTask() 的通用方法来同时处理这两种类型的 请求,不过您可以基于触发 servlet 调用的 HTTP 类型而使用不同的处理。

编程式导航

在代码中从一个资源导航到另一个资源的情况在 Web 应用程序中是相当普遍的。导航与 应用程序状态密切相关,因为当您在一系列资源中导航时,可能需要维护状态信息。与 ASP 比较而言,J2EE 提供更多的选项进行编程式导航。

ASP 使用 RESPONSE.REDIRECT() 函数支持编程式导航。J2EE 支持以下形式的编程式导航 :

使用 HttpServletResponse.sendRedirect() 方法 :这会导致向客户端浏览器返回一个 特殊的 HTTP 返回代码(连同要重定向的页面),然后客户端浏览器又对重定向的目标发出 新的请求。如果需要在这两个请求之间共享数据,那就必须将数据存储在会话或应用程序范 围中。这类似于 ASP 中的 RESPONSE.REDIRECT() 函数。

使用 servlet 中的 RequestDispatcher.forward() 方法或 JSP 页面中的特殊标签: 这 会导致调用此方法的资源终止,同时终止对作为转发目标的资源的调用。对客户端浏览器来 说,这看起来就像是单个请求。例如,如果将请求从 servlet 转发到 JSP 页面,则您可能 要附加该 servlet 中的某些处理结果,以便这些结果可以在 JSP 页面中显示出来。

使用 RequestDispatcher.include() 方法或 JSP 页面中的特殊标签 :这会导致调用此 方法的资源挂起,同时挂起对目标资源的调用。当目标资源完成时,挂起的资源又继续处理 。对客户端浏览器来说,这看起来就像是单个请求。

清单 33 包括了 JSP 页面中这些导航方法的一些例子。

清单 33. JSP 页面中的编程式导航

清单 34 展示了 servlet 中这些导航方法的一些例子。

清单 34. servlet 中的编程式导航

public void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  ...   // Redirecting to another resourceresponse.sendRedirect("anotherResource.jsp");  ...}// This code snippet shows the use of a RequestDispatcher to forward to another resourcepublic void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  ...  // Get a RequestDispatcher instance  RequestDispatcher rd = getServletContext().getRequestDispatcher ("anotherResource.jsp");  // Forward the request  rd.forward(request, response);  ...}// This code snippet shows the use of a RequestDispatcher to include another resourcepublic void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  ...  // Get a RequestDispatcher instance  RequestDispatcher rd = getServletContext().getRequestDispatcher ("anotherResource.jsp");  // Forward the request  rd.include(request, response);  // Continue processing the request  ...}

Cookie

在 ASP 中,cookie 的处理使用了 REQUEST 和 RESPONSE 对象的 Cookies 属性。 RESPONSE 对象用于创建 cookie,而 REQUEST 对象用于检索 cookie 值。为方面起见,在代 码中使用了多值 cookie,尽管多值 cookie 被编码到 HTTP 响应表头时,但是可以转换为单 值 cookie。

在 J2EE 中,cookie 由 Cookie 类表示,并通过 HttpServletRequest 和 HttpServletResponse 接口来访问。您可以使用 HttpServletRequest 接口访问现有的 cookie,使用 HttpServletResponse 接口来创建 cookie。

清单 35 演示了如何在 J2EE 应用程序中使用 cookie。您可以在 Java Servlet 或 JSP 页面的 scriptlet 中使用这些代码片断。

清单 35. 在 J2EE Web 应用程序使用 cookie

// Create a cookie using the HttpServletResponse interface// The first parameter of the construcTor is the name of the cookie// and the second parameter is the cookie's valueCookie myCookie = new Cookie("myCookie", "someValue");// Set the age of the cookie - by default cookies will be sTored in memory// by the browser and will be destroyed when the user closes the browser// The setMaxAge() methods takes an integer as its parameter which represents// the age in seconds. In this example we're specifying an age of 24 hours for// the cookiemyCookie.setMaxAge(86400);// Add cookie to the responseresponse.addCookie(myCookie);// Here's an example of retrieving cookies from the HttpServletRequest interface// Note that the cookies are returned as an array of Cookie objectsCookies[] myCookies = request.getCookies();// The getCookies method will return null if there are no cookiesif (myCookies != null) {  for (int i = 0; i < myCookies.length; i++) {    Cookie eachCookie = myCookies[i];    // Do something w/each cookie    ....  }}

结束语

感谢您使用这个关于 J2EE 开发的入门教程。我们已尽力提供足够的信息使您走上 J2EE 之路,并且使您的开放标准编程之旅尽可能的顺利。我们鼓励您利用本文的 参考资料小节以 继续接受 J2EE 教育。祝旅途愉快。

接受失败等于放松自己高压的心理,

走上开放之路:ASP开发人员的J2EE基础(下)

相关文章:

你感兴趣的文章:

标签云: