|
虽然有多种技术可用于生成为动态内容提供服务的 web 应用程序,但真正受 到开发界青睐的是 JavaServer PagesTM (JSPTM)。这并非没有充分的理由。JSP 不仅 拥有跨平台和跨 Web 服务器支持,并且将服务器端 Java 技术的功能与静态 HTML 页的“所见即所得”功能有效地结合了起来。
典型的JSP 页由以下几部分组成:
- 静态 HTML/XML 组件。
- 专用 JSP 标记
- 可选)用 Java 编程语言编写的代码片断,称为“脚本小程序”。
因此,您可以用常规的 HTML/XML 工具创建和维护 JSP 页。
有必要指出:JSP 规范是在 Servlet API 上定义的标准扩展。因此,您可以 利用所有与 servlet 相关的经验。
JSP 和 servlet 技术之间区别很大。servlet 是一种编程技术,对开发人员 的专门知识技能要求很高;而 JSP 与 servlet 不同,它适合更广泛的使用者。 不仅开发人员可以使用它,页面设计人员也可以使用它,从而使其在开发周期中 扮演更为直接的角色。
JSP 的另一个优点是演示与使用 JSP 技术的内容的分离,这归功于 JSP 对可 重用组件技术(例如 JavaBeansTM 组件体系 结构和企业级 JavaBeansTM 技术)的依赖。 本教程向您深入介绍这种多能的技术,并使用 Apache 集团的 Tomcat JSP 1.1 Reference Implementation 来运行示例程序。
静态内容和动态内容的分离: 对于 servlet,动态内容的生成逻辑是 servlet 本身的固有部分,与负责用户界面的静态演示模板紧密关联。因此,即 使对 UI 所作的微小更改,通常也会导致重新编译 servlet。演示与内容的这种 紧密结合使得应用程序脆弱而不灵活。但是,对于 JSP,通过将生成动态内容的 逻辑封装到外部 JavaBeans 组件中,可使该逻辑与静态演示模板保持着分离。从 而使用特殊标记和脚本小程序的 JSP 页创建并使用这些组件。当页面设计人员对 演示模板作任何更改时,JSP 引擎便会自动重新编译 JSP 页,并将其重新加载 到 web 服务器中。
一次编写,随处运行: JSP 技术将“一次编写,随处运行”的范例推 广到了交互网页中。不需要作任何更改,就可以很轻松地跨平台和跨 Web 服务器 移动 JSP 页。
可以用多种格式为动态内容提供服务: 没有任何机制使 JSP 页中的静 态模板采用特定的格式。因此,JSP 可以为不同的客户端(包括使用 HTML/DHTML 的常规浏览器、使用 WML 的移动电话和 PDA 等手持式无线设备和使用 XML 的其 他 B2B 应用程序)提供服务。
推荐的用于 n 层体系结构的 Web 访问层: Sun 的 J2EETM,蓝图为使用企业级 Java API 开发大规模的应用程序提供了一些准则,它明确推荐使用 JSP(而不要使用 servlet)为动态内容提供服务。
完全利用 Servlet API: 如果您是 servlet 开发人员,若要转到 JSP,所掌握的知识技能几乎没有什么必须摈弃的。事实上,servlet 开发人员有 明显的优势,因为 JSP 只是对 servlet 的高级提炼。使用 JSP,您几乎可以做 任何使用 servlet 可以做的事情,并且更加容易!
尽管 JSP 提供的功能看起来与 Microsoft 的 Active Server Page (ASP) 的 功能相似,但这两种技术有根本的区别,如下表所示:
|
JavaServer 页 |
Active Server 页 |
| Web 服务器支持 |
使用 JSP,很容易启用多数常用的 Web 服 务器(包括 Apache、Netscape 和 Microsoft IIS)。 |
仅在 Microsoft IIS 或 Personal Web Server 中提供本机支持。支持选择的使用第三方产品的服务器。 |
| 平台支持 |
不受平台影响。在所有启用 Java 的平台 上运行。Windows 下对它完全支持。 |
在其他平台上部署较麻烦,因为它依赖基 于 Win32 的组件模型。 |
| 组件模型 |
依赖可重用的跨平台组件,如 JavaBean、 企业级 JavaBean 和自定义标记库。 |
使用基于 Win32 的 COM 组件模型。 |
| 脚本撰写 |
可以使用 Java 编程语言或 JavaScript。 支持使用 VBScript 和 JScript 进行脚本撰写。 |
安全性 使用 Java 安全模型。可以使 用 Windows NT 安全体系结构。 |
| 安全性 |
使用 Java 安全模型。 |
可以使用 Windows NT 安全体系结构。 |
| 数据库访问 |
使用 JDBC 来访问数据。 |
使用活动数据对象来访问数据。/TD> |
| 可自定义的标记 |
可以使用自定义的标记库扩展 JSP。 |
不能使用自定义标记库,且不能扩展。 |
servlet 和 JSP 页确实有许多相同之处,并且都可以用来为动态 Web 内容提 供服务。对于何时选择其中的一种技术而不选择另一种技术,这自然会带来一些 混淆。所幸的是,Sun 的 J2EE 蓝图对此提供了一些准则。
根据该蓝图,严格地将 servlet 用作 Web 服务器扩展技术。这可包括提供认 证、数据库验证等服务的专用控件器组件的实现。注意,有趣的是,通常所说的 “JSP 引擎”本身是一个在 servlet 引擎控制下运行的专用 servlet。由于 JSP 仅处理文本数据,因而您在与 Java applet和应用程序进行通信时必须继续 使用 servlet。
使用 JSP 开发典型的依赖动态内容的 Web 应用程序。还应当使用 JSP 来代 替服务器端包含文件之类的专有 Web 服务器扩展,因为 JSP 具有优异的处理重 复内容的功能。
练习
- 安装和配置 Tomcat
JSP 的用途是提供声明的、以演示为中心的开发 servlet 的方法。正如前面 所指出的那样,JSP 规范本身被定义为 Servlet API 上的标准扩展。因此,在实 质上,servlet 和 JSP 页有许多相同之处,这并不会令人感到十分奇怪。
通常,JSP 页具有翻译阶段和请求处理阶段。除非 JSP 页更改(在这种情况 下翻译阶段会重复),否则翻译阶段仅执行一次。假定页面中没有语法错误,翻 译结果是一个 JSP 页实现类文件,该文件实现 Servlet 接口,如下所示。
当 JSP 引擎首次收到传入的对 JSP 页的请求时,JSP 引擎本身通常会执行翻 译阶段。注意,JSP 1.1 规范还允许将 JSP 页预编译到类文件中。对于移除当以 源代码形式传递的 JSP 页从客户端接收到第一个请求时发生的启动日志,预编译 尤其有用。翻译阶段的许多细节(如源文件和类文件的存储位置)都依赖实现。 Tomcat 为此 JSP 页示例(展示在上图中)生成的类文件的源代码如下:
package jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Vector;
import org.apache.jasper.runtime.*;
import java.beans.*;
import org.apache.jasper.JasperException;
import java.text.*;
import java.util.*;
public class _0005cjsp_0005cjsptest_0002ejspjsptest_jsp_0
extends HttpJspBase {
static {
}
public _0005cjsp_0005cjsptest_0002ejspjsptest_jsp_0( ) {
}
private static boolean _jspx_inited = false;
public final void _jspx_init() throws JasperException {
}
public void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
String _value = null;
try {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this,
request,response, "", true, 8192, true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
// begin
out.write("\r\n<html>\r\n<body>\r\n");
// end
// begin [file="E:\\jsp\\jsptest.jsp";from=(3,2);to=(5,0)]
Date d = new Date();
String today = DateFormat.getDateInstance().format(d);
// end
// begin
out.write("\r\nToday is: \r\n<em> ");
// end
// begin [file="E:\\jsp\\jsptest.jsp";from=(7,8);to=(7,13)]
out.print(today);</b>
// end
// begin
out.write(" </em>\r\n</body>\r\n</html>\r\n");
// end
} catch (Exception ex) {
if (out.getBufferSize() != 0)
out.clear();
pageContext.handlePageException(ex);
} finally {
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
}
}
JSP 页实现类文件扩展 HttpJspBase,HttpJspBase 转而实现 Servlet 接口。观察此类的服务方法 _jspService() 如何在实质上内嵌了 JSP 页的内容。尽管无法忽略 _jspService(), 但开发人员可通过在他们的 JSP 页中提供jspInit() 和 jspDestroy() 两个方法的实现来描述初始化事件和毁坏事件。
一旦在 servlet 容件中加载此类文件后,_jspService() 方法 便会负责回复客户端的请求。默认情况下,在处理并发客户端请求时,servlet 容件会在一个单独的线程上分派 _jspService() 方法,如下所示:
早期的 JSP 规范提出了两种应用 JSP 技术的理论方法,通常称为 Model 1 和 Model 2 体系结构。这两种方法主要在请求处理主体的执行位置上有区别,它 们为使用 JSP 技术生成应用程序提供了一个有用的范例。
试考虑 Model 1 体系结构,如下所示:
在 Model 1 体系结构中,从 Web 浏览器传入的请求直接发送到 JSP 页,该 页负责处理请求及回复客户端。演示与内容仍然分离,因为所有数据访问都是通 过使用 bean 执行的。
尽管 Model 1 体系结构适合简单应用程序,但可能不适合复杂的实现。不加 选择地使用这种体系结构通常会使大量脚本小程序或 Java 代码嵌入到 JSP 页中, 尤其在有大量请求处理需要执行时更是如此。虽然这对 Java 开发人员似乎不是 一个大问题,但如果您的 JSP 页由设计人员创建并维护(大型项目通常如此), 这肯定是一个问题。这种体系结构的另一个缺陷是,每个 JSP 页必须单独负责管 理应用程序状态和验证认证与安全性。
上面展示的 Model 2 体系结构是常见的“模型/视图/控制器”设计模式的服 务器端实现。这里将处理在演示和前端组件之间作了划分。演示组件是生成 HTML/XML 响应的 JSP 页,负责在浏览器呈现用户界面时确定用户界面。前端组 件(又称控制器)不处理任何演示问题,而处理所有的 HTTP 请求。这里,它们 负责创建演示组件使用的任何 bean 或对象,并根据用户的操作确定向哪个演示 组件转发请求。可以将前端组件作为 servlet 或 JSP 页来实现。
这种体系结构的优点是,演示组件本身没有处理逻辑;它只负责检索由控制器 以前创建的任何对象或 bean,并负责提取用于插入到其静态模板中的动态内容。 这样,演示与内容的清晰分离,使编程组中的开发人员和页面设计人员的角色和 责任得以清晰描绘。此方法的另一好处是,前端组件提供了单个进入应用程序的 入口点,从而使应用程序状态、安全性和演示既统一而又易于维护。
JSP 语法相当简单,可以分为指令、脚本元素和标准操作。
JSP 指令就是向 JSP 引擎发出的消息。它们不会直接产生任何可见的输出, 但会告诉引擎如何处理 JSP 页的其他部分。JSP 指令总是被放在 <%@ ... %> 标记中。两种主要的指令是 page 和 include。(注 意,JSP 1.1 还提供 taglib 指令,该指令可用于处理自定义标记 库,不过这里不讨论它。)
通常,几乎在所有 JSP 页顶部都可找到 page 指令。一个 JSP 页内可以有任意数量的 page 指令,不过属性/值对必须唯一。未被 识别的属性或值会导致翻译错误。例如,
<%@ page import="java.util.*, com.foo.*" buffer="16k" %>
上面的代码将为脚本撰写提供包含的包中声明的类型,并将页面缓冲区设置 为 16K。
include 指令让您将内容分成更容易管理的元素,例如那些用 于包含公共页眉或页脚的元素。包含的页面可以是一个静态 HTML 页或更多的 JSP 内容。例如:
<%@ include file="copyright.html" %>
上面的指令可用于在 JSP 页中任意位置,它包含指示的文件的内容。
JSP 声明让您定义页面级别的变量以保存信息,或定义 JSP 页的其他部分可能 需要的支持方法。虽然盲目地让您的 JSP 页中有很多代码是一件轻松的事情,但 这样做最终会使维护成为一场噩梦。为此,同时也是为了增强可重用性,最好将逻辑密集的处理封装为 JavaBean 组件。
声明见于 <%! ... %> 标记中。应始终以分号结束变量 声明,因为任何内容都必须是有效的 Java 语句:
<%! int i=0; %>
您还可以声明方法。例如,通过声明以下内容可以忽略 JSP 生存期中的初始 化事件:
<%! public void jspInit() {
//some initialization code
}
%>
利用 JSP 中的表达式,表达式求值的结果将转换为一个字符串,并会直接包 含到输出页中。通常,表达式用于通过调用 bean 的获取器方法显示简单变量值 或返回值。JSP 表达式在 <%= ... %> 标记内开始,且不包 含分号:/P>
<%= fooVariable %>
<%= fooBean.getName() %>
JSP 代码片断或脚本小程序嵌入在 <% ... %> 标记中。 当 JSP 页为请求提供服务时,就会运行此 Java 代码。脚本小程序内可以有任意 有效 Java 代码,而不限于有一行源代码。例如,通过联合使用表达式和脚本小 程序,下面的代码会在 H1、H2、H3 和 H4 标记内显示字符串“Hello”:
<% for (int i=1; i<=4; i++) { %>
<H<%=i%>>Hello</H<%=i%>>
<% } %>
您总可以在 JSP 页中包含 HTML 注释,用户在查看页的源代码时可查看这些 注释。但如果您不想让用户能够查看您的注释,请将注释嵌入到 <%-- ... --%> 标记中:
<%-- comment for server side only --%>
JSP 注释的最有用功能是,可以使用注释来有选择地禁止编译某些脚本小程序 或标记。这样,注释可以在调试和测试过程中发挥重要作用。
在讲述 JSP 语法和语义之前,理解正在处理请求的 JSP 页中 Java 对象的范 围或可见性很重要。可以隐式地使用 JSP 指令、显式地通过操作或直接使用脚本 代码(这种情况较少)来创建对象。可以将实例化的对象与一个范围属性相关联, 该范围属性定义何处有对该对象的引用以及何时移除该引用。下图指出了可以与 新创建的对象关联的各种范围:
作为一种便利的功能,JSP 容件提供一些可用在脚本小程序和表达式中的隐式 对象,而不必让页面作者先创建这些对象。这些对象用作 Servlet API 中通常定 义的基础 Java 类或接口的包装。九个隐式对象列举如下:
注意,这些隐式对象仅在系统生成的 _jspService() 方法中可 见。它们在声明中您自己定义的方法中是不可见的。
默认情况下,JSP 页实现类的为客户端请求提供服务的服务方法是多线程的。 因此,JSP 页作者应负责确保有效地同步对共享状态的访问。有几种不同的方式 可以确保服务方法是线程安全的。较简便的方式是包含 JSP page 指令:
<%@ page isThreadSafe="false" %>
这会使 JSP 页的实现类实现 SingleThreadModel 接口,从而 使服务方法得以同步,并使 servlet 的多个实例加载到内存中。并发的客户端请 求于是会平均分发给这些实例,然后一连串地进行处理,如下所示:
使用这种方式的缺陷是不可缩放。如果因存在大量并发请求(影响对 servlet 实例的处理能力)而使等候队列增大,则客户端在获取响应时可能会出现严重的 延迟。
较好的方式是使用脚本小程序,在 JSP 页中显式地同步对共享对象(例如那 些拥有应用程序范围的实例)的访问:
<%
synchronized (application) {
SharedObject foo = (SharedObject)
application.getAttribute("sharedObject");
foo.update(someValue);
application.setAttribute("sharedObject",foo);
}
%>
JSP 提供了一种相当优秀的处理运行时间异常的机制。虽然您可以在 JSP 页 中提供您自己的异常处理,但可能无法预见所有情况。通过利用 page 指令的 errorPage 属性,可以将未捕获的异常转发给一个错误处 理 JSP 页来处理。例如,
<%@ page isErrorPage="false" errorPage="errorHandler.jsp" %>
上面的代码通知 JSP 引擎将任何未捕获的异常转发给 JSP 页的 errorHandler.jsp。这时,errorHandler.jsp 有必 要使用下面的指令将它自身标记为一个错误处理页:
<%@ page isErrorPage="true" %>
这样便允许在脚本小程序内通过隐式异常对象来访问描述异常的 Throwable 对象。
练习
- JSP 中的异常处理
默认情况下,所有 JSP 页都参与 HTTP 会话。可以在脚本小程序内通过会话的 隐式 JSP 对象访问 HttpSession 对象。对于用户可能访问的其他 JSP 页和 servlet 共享的 bean 和对象,会话 是一个良好的存储场所。会话对象由会话 ID 标识,以 cookie 形式存储在浏览 器中。如果浏览器不支持 cookie,则可通过改写 URL 来维护会话 ID。JSP 规范 不允许支持改写 URL;仅在少数服务器中支持改写 URL。虽然您不能将原始数据 类型放到会话中,但您可以通过以一个唯一的关键字标识任何有效的 Java 对象 来将其存储到会话中。例如:
<%
Foo foo = new Foo();
session.putValue("foo",foo);
%>
上面的代码在属于同一会话的所有 JSP 页和 servlet 中提供 Foo 实例。可以在不同的 JSP 页中将该实例检索为:
<%
Foo myFoo = (Foo) session.getValue("foo");
%>
对 session.getValue() 的调用会返回一个对一般的 Object 类型的引用。因此,每次都要将返回的值强制转换为适当的数据类型然后再使用, 这一点很重要。不强制 JSP 页参与会话;它们可以通过设置 page 指令的适当属性来选择不参与会话:
<%@ page session="false" %>
可以存储到会话中的对象的数目不受限制。但是,将大型对象放到会话中可能 会降低性能,因为这类对象会占用宝贵的堆空间。默认情况下,多数服务器将会 话对象的生存期设置为 30 分钟,不过您可以通过对会话对象调用 setMaxInvalidationInterval(int secs) 来一个会话一个会话地 重新设置生存期。下图着重说明会话管理的一般体系结构:
只要会话有效,JSP 引擎就对放置在会话中的对象保持一个活动引用。如果会 话无效或者遇到了会话超时,则其中的对象将标记为等待垃圾回收。
允许您执行复杂任务(如实例化对象,以及与 JSP 页和 servlet 之类的服务 器端资源进行通信)而不要求 Java 编码的操作。虽然在脚本小程序中使用 Java 代码可以实现同样的目的,但使用操作标记可提高您的组件的可重用性,并 可增强应用程序的易管理性。
JSP 技术的组件模型基于 JavaBeans 组件体系结构。JavaBeans 组件就是遵 循定义好的设计/命名模式的 Java 对象: bean 通过将其属性声明为私有来封装 这些属性,并提供公共的访问器(获取器/设置器)方法来读取和修改它们的值。
在 JSP 页内访问 bean 之前,有必要标识该 bean 并获取对它的引用。 <jsp:useBean>标记尝试使用指定的标识和范围来获取对现 有实例的引用,因为以前可能已经创建了该 bean,并且放到了一个不同的 JSP 页内的会话或应用程序范围中。只有在从指定的范围中未获得引用时,才使用指 定的 Java 类名通过类属性重新实例化该 bean。试考虑下面的标记:
<jsp:useBean id="user" class="com.jguru.Person"
scope="session" />
在此示例中,Person 实例仅创建了一次,并且放到了会话中。 如果后来在一个不同的 JSP 页中遇到了此 useBean 标记,则会从 会话中检索到一个对以前创建的旧实例的引用。
<jsp:useBean> 标记也可以包含一个体,例如
<jsp:useBean id="user" class="com.jguru.Person"
scope="session">
<%
user.setDate(DateFormat.getDateInstance(
).format(new Date()));
//etc..
%>
</jsp:useBean>
<jsp:useBean> 标记体中的任何脚本小程序(或 <jsp:setProperty> 标记,稍后将解释)都是在实例化 bean 时才执行,并被用来实例化 bean 的属性。
声明一个 JavaBean 组件后,可以访问它的属性来自定义它。应使用 <jsp:getProperty> 标记来访问 bean 的属性的值。使用 <jsp:getProperty> 标记,可以指定要使用的 bean 的名 称(从 useBean 的标识字段),以及您关心其值的属性的名称。 实际的值这时会直接打印到输出中:
<jsp:getProperty name="user" property="name" />
更改 JavaBean 组件的属性要求您使用 <jsp:setProperty> 标记。对于此标记,您应标识要修改的 bean 和属性并提供新值:
<jsp:setProperty name="user" property="name"
value="jGuru" />
或者
<jsp:setProperty name="user" property="name"
value="<%=expression %>" />
在为处理窗体数据而开发 bean 时,您可以通过让 bean 属性的名称与窗体输 入元素的名称相匹配,来遵循一个常用的设计模式。您还需要为 bean 中的每个 属性定义相应的获取器/设置器方法。这样做的优点是,您现在可以指示 JSP 引 擎分析从属于请求对象的一部分的 HTML 窗体元素中传入的所有值,然后使用单 个语句将这些值赋给对应的 bean 属性,例如:
<jsp:setProperty name="user" property="*"/>
这种运行时技巧可通过一种称为反省的过程来实现,该过程让类在接到请求时 公开其属性。这种反省由 JSP 引擎管理,通过 Java 反向机制实现。这种功能本 身可以在处理包含大量输入元素的复杂窗体时用作急救器。
如果您的 bean 属性的名称不匹配窗体的输入元素的名称,仍可以将它们显式 映射为您的属性,方法是将参数命名为:
<jsp:setProperty name="user" property="address"
param="parameterName" />
练习
- 理解 JSP 对象范围
- 使用 JSP 进行窗体处理
使用 <jsp:forward> 标记,您可以将请求重定向到调用 页面所在的上下文中的任何 JSP、servlet 或 静态 HTML 页。这会在重定向发生 时暂停当前页的处理,但在此之前,所有处理仍在进行。
<jsp:forward page="somePage.jsp" />
调用页面也可传递目标资源 bean 参数,方法是将这些参数放到请求中,如图 所示:
<jsp:forward> 标记还可以有 jsp:param 子元素,这些子元素可为转发过程中使用的请求中的一些元素提供值:
<jsp:forward page="<%= somePage %>" >
<jsp:param name="name1" value="value1" />
<jsp:param name="name2" value="value2" />
</jsp:forward>
请求链是一种强大的功能,可用来有效地联合 JSP 页和 servlet 来处理 HTML 窗体,如下图所示:
试考虑下面的 JSP 页,例如 Bean1.jsp,该页创建了一个 FormBean类型的命名实例 fBean,将该实例放到了 请求中,并将调用转发给了 servlet JSP2Servlet。观察实例化 bean 的方式——这里我们为匹配所张贴的窗体元素名称的属性自动调用 bean 的 设置器方法,同时将对应的值传递给方法。
<jsp:useBean id="fBean" class="govi.FormBean"
scope="request"/>
<jsp:setProperty name="fBean" property="*" />
<jsp:forward page="/servlet/JSP2Servlet" />
JSP2Servlet 此时从请求提取向它传递的值,使用相应的设置 器进行一些更改,然后使用请求调度程序将调用转发给另一个 JSP 页 Bean2.jsp。 注意,此 servlet 充当控制器,如果需要,它还可以将更多的 bean 放到请求中。
public void doPost (HttpServletRequest request,
HttpServletResponse response) {
try {
FormBean f = (FormBean) request.getAttribute
("fBean");
f.setName("Mogambo");
// do whatever else necessary
getServletConfig().getServletContext().
getRequestDispatcher("/jsp/Bean2.jsp").
forward(request, response);
} catch (Exception ex) {
. . .
}
}
JSP 页 Bean2.jsp 此时可以从请求中提取 bean fBean (以及控制器 servlet 可能已经传递的任何其他 bean),并提取其属性。
<html>
<body>
<jsp:useBean id="fBean" class="govi.FormBean"
scope="request"/>
<jsp:getProperty name="fBean" property="name" />
</body>
</html>
<jsp:include> 标记可用来将请求重定向给调用 JSP 页 所在的上下文中的任何静态或动态资源。调用页面也可传递目标资源 bean 参数, 方法是将这些参数放到请求中,如图所示:
例如:
<jsp:include page="shoppingcart.jsp" flush="true"/>
上面的代码不仅允许 shoppingcart.jsp 访问任何放在使用 <jsp:useBean> 标记的请求中的 bean,而且它所生成的动 态内容会插入到调用页面中有 <jsp:include> 标记的位置。 但包含的资源无法设置任何 HTTP 标头,这会禁止它执行诸如设置 cookie 之类 的操作,否则会引发异常。
下面的站点拥有产品信息以及有关 JSP 和 servlet 的白皮书:
Sun Microsystems 的 Java 技术站点 包含一个“产品 & API”页, 该页列出了与企业相关的产品和 API。其中一些与 JSP 相关的产品和 API 列举 如下:
下面是一些关于 JSP 计算技术的文章:
版权所有 1996-2000 jGuru.com。保 留所有权利。
|