当前位置:编程学习 > JSP >>

J2EE探索者:隐式对象的多种用法

答案:接着上月对会话作用域的介绍,企业 Java 专家 Kyle Gabhart 深入研究了 JSP 隐式对象的多种用法。接下来,他将介绍 9 个隐式对象,解释每个对象的用途(或者多种用途),最后给出一些怎样在 JSP 编程中使用这些便利工具的最佳实践。您可以到我们的 讨论论坛 中分享您对这篇文章或者 J2EE 探索者 系列中的任何其他文章的想法。
本期的 J2EE探索者 是上个月的 正确处理会话作用域入门 的续篇。除了访问会话作用域之外,JSP 隐式对象还可以用来处理 HTML 参数,转发请求到一个 Web 组件,包括组件的内容、通过 JSP 容器的日志数据、控制输出流,处理异常,等等。

本月,您将学到在 JSP 页面中使用隐式对象。我们首先简要概括 JSP 架构,其中包括了隐式对象。然后,我将介绍每个对象并描述它的核心功能。最后,我们将给出使用每种类型的对象和它提供的容器管理服务的一些最佳实践。

隐式对象简介
JSP 架构背后的理念是提供一个 Web 组件,它允许开发人员着重关注 Web 内容的表示,而不用陷入解析、编程和数据操纵等细节。JSP 应用程序本质上是特殊的 Web 组件,在处理用户请求之前,J2EE Web 容器首先将其转换成 servlet。在每个 JSP 应用程序内部有一套完整的隐式对象。

隐式对象使得开发人员可以访问容器提供的服务和资源。这些对象之所以定义为隐式的,是因为您不必显式地声明它们。不论您是否声明它们——虽然您不能重复声明它们,它们在每个 JSP 页面当中都进行定义,并且在后台由容器使用。因为隐式对象是自动声明的,所以我们只需要使用与一个给定对象相关的引用变量来调用其方法。

9 个隐式对象及其功能的简单描述如下:

Application 是使用范围最广的上下文状态。它允许 JSP 页面的 servlet 与包括在同一应用程序中的任何 Web 组件共享信息。


Config 允许将初始化数据传递给一个 JSP 页面的 servlet。


Exceptioninclude 含有只能由指定的 JSP“error pages”访问的异常数据。


Out 提供对 servlet 的输出流的访问。


Page 是JSP页面的处理当前请求的 servlet 的实例。一般来说,JSP 页面作者不使用该对象。


PageContext 是 JSP 页面本身的上下文。它提供惟一一个 API 来管理具有不同作用域的属性。这个 API 在实现 JSP 自定义标记处理程序时使用得非常多。


Request 提供对 HTTP 请求数据的访问,同时还提供用于加入特定于请求的数据的上下文。


Response 允许直接访问 HTTPServletResponse 对象,JSP 程序员很少使用该对象。


Session 可能是状态管理上下文中使用得最多的对象。“会话”的概念是指单个用户与 Web 应用程序在几个请求上进行交互。
虽然有些隐式对象只提供单一的功能,但是几个结合起来使用就可以提供多种功能。在接下来的一节里,我们将按照功能分类来考察隐式对象:

会话管理:application, session, request, pageContext
流控制:application, config, pageContext, request, session
日志记录和异常:application, config, exception, pageContext, request, session
输入/输出控制:request, response, out
初始化参数:config
会话管理
上个月我们提到过,为 JSP 定义的四个隐式对象可以用来在一个特定的上下文或者作用域中加入有状态数据。这四个对象是 application、session、request 和 pageContext。下表列出了这四个对象和它们定义的状态上下文,同时还给出了对每个对象的简单描述。

表1. JSP 状态管理 隐式对象 作用域 描述
javax.servlet.ServletContext Application 代表整个运行时的 Web 模块(应用程序)。作用域为 application 的数据在同一个应用程序模块的所有 Web 组件之间共享。这很像J2EE 中提供的“全局(global)”数据
javax.servlet.http.HttpSession Session 代表当前的 HTTP 会话。除 page 作用域外,session 作用域是使用最普遍的上下文。这个对象在提供跨多个请求的持久的、有状态的用户体验方面使用得最普遍
javax.servlet.http.HttpServletRequest Request 代表当前的 HTTP 请求。这个上下文可以跨越多个 Web 组件(servlet 和 JSP 页面),只要这些组件属于同一原子请求的一部分。由客户机提供的特定于请求的数据(请求方法、URI、HTTP 参数等等)都被自动地保存在一个request 上下文中。servlet 或 JSP 页面还可以程式化地(programmatically)将数据的作用域指定为 request,以便允许同一 request 作用域中的其他 servlet 或 JSP 页面可以获取该数据
javax.servlet.jsp.PageContext Page 代表当前 JSP 页面的上下文。因为一个 JSP 页面的上下文包括当前的请求、会话和应用程序,所以使用pageContext 实例可以访问与一个JSP 页面相关的所有命名空间。它是所有对象的默认作用域,包括 JavaBeas 对象在内。 具有 page 作用域的对象通常会绑定到一个局部变量,以便在 scriptlet、表达式、JavaBeans 标记和自定义标记中可以访问它


从最佳实践的立场来看,我们应该尽可能地使用 page 作用域。它简单,而且是 JSP 数据的默认作用域。request 作用域非常适合于运行期间在组件间共享数据以处理一个特定的请求。session 作用域被设计用来为单个用户提供持久的、有状态的体验,它可以跨越多个请求。application 作用域只有需要在组件之间跨用户会话共享数据时才应该使用。参阅参考资料以了解更多有关 session 作用域的信息。

流控制
面向对象设计方法的最大好处是可重用性。特别是,J2EE 系统将它们借用到模块化风格的开发中,其中组件可以在其他应用程序中重新安排、重新打包和重新使用。即使您对设计可重用的 Web 模块不感兴趣,也很可能会发现您的 J2EE 应用程序由几个部分组成。任何时候使用多个 servlet 或者 JSP 页面(也就是组件)完成一个请求的时候,都需要使用某种类型的流控制技术。Servlet 架构提供两种这样的技术:forward(转发) 和 include(包括)。

在 J2EE Web 开发中,forward 会把处理用户请求的控制权转交给到其他 Web 组件。forward 在有些时候会比较有用,比如说需要用一个组件设置一些 JavaBean、打开或关闭资源、认证用户,或者在将控制权传递给下一个组件之前需要执行一些准备工作。在转发之前可以执行很多类型的任务,但是要转发的组件不能设置响应头部信息,也不能有内容发送到输出缓冲区。所有与向客户发送内容直接相关的任务必须由被转发的组件完成。

J2EE 中第二种流控制技术是include。在使用 forward 时,要传递控制权。与此不同的是,执行 include 的组件维持对请求的控制权,而只是简单地请求将另一个组件的输出包括在该页面的某个特定的地方。对于常见的设计元素,例如页首、页脚和导航栏等,这是一个非常好的方法。

forward 和 include 都是通过一个专门的对象 java.servlet.RequestDispatcher 来完成的。简单地调用一个 ServletContext 对象的 getRequestDispatcher()方法就可以获得一个RequestDispatcher 对象。得到对 ServletContext 对象的引用有几种方法,我们可以:

使用隐式声明的 application 变量,因为它的类型本身已经是 ServletContext。
调用方法 getServletContext(),该方法返回一个对隐式声明的 application 变量的引用。
调用隐式声明的 config 变量的 getServletContext()方法。
调用隐式声明的 pageContext 变量的 getServletContext()方法。
调用隐式声明的 request 变量的 getServletContext()方法。
调用隐式声明的 session 变量的 getServletContext()方法。
清单1给出了使用隐式变量 application 的 forward 流控制机制的代码示例。

清单1. forward 流控制示例

javax.servlet.RequestDispatcher rd;

/* Obtain a reference to a RequestDispatcher object via the implicit
application variable*/
rd = application.getRequestDispatcher( "/NextPage.jsp" );

/* Perform the forward specified by the RequestDispatcher
and pass along a reference to the current request and
response objects */
rd.forward( request, response );



清单2给出了同样使用变量 application 的 include 流控制的代码示例。

清单2. include 流控制示例

javax.servlet.RequestDispatcher rd;

/* Obtain a reference to a RequestDispatcher object via the implicit
application variable*/
rd = application.getRequestDispatcher( "/Header.jsp" );

/* Perform the include specified by the RequestDispatcher
and pass along a reference to the current request and
response objects */
rd.include( request, response );



forward 和 include 是添加到 J2EE Web 开发工具包中的两个非常棒的技术。还有其他一些方法可以在 JSP 页面中完成 include,而且还有很多解决 J2EE 设计模式方面的文献中讲到了如何结合使用这两种技术。参阅参考资料以了解更多信息。

日志记录和异常
如果您需要把与 Web 应用程序相关的信息存储到一个日志中,依然有内建的方法可用。ServletContext 接口声明了两个方法,用于把数据传给一个日志。其中一个方法接受简单的文本消息:log( java.lang.String ),另一个方法接受一个异常信息和一个文本消息:log(java.lang.Throwable, java.lang.String )。

在有了 ServletContext 接口提供的两个可用的日志记录方法之后,剩下的关键是获取一个对ServletContext 类型的对象的引用。像我们前面讨论过的流控制对象一样,有多种方法可以获取对 ServletContext 类型的对象的引用。

上一个:J2EE 探险者:持久数据管理,第 1 部分
下一个:Oracle9iAS Containers for J2EE独立版指南--(配置数据源与调用)

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,