作者:Qusay H. Mahmoud
2003年7月
JSP(JavaServer Pages)技术是对Servlet的进一步抽象,它由JCP(Java Community Process)开发,是用于生成动态内容的开放式的、可免费获取的规范,也是J2EE(Java 2 Enterprise Edition)规范的重要组成部分。许多商业应用服务器如BEA WebLogic、IBM WebSphere、Live Jrun和Orion都支持JSP技术。
从机票预订系统、银行系统到购物系统,Web上到处都在应用JSP技术。新发布的2.0版是对JSP1.2的升级,增加了一些有趣的新特性。JSP2的目标是使动态网页的设计更加容易,而且无需学习Java编程语言。
本文内容包括:
- 提供具有丰富示例代码的教程来使你熟悉JSP2.0
- 介绍JSP2.0的新特性
- 提供利用JSP2.0开发应用程序的一些体会
- 给出了一些示例代码,对这些代码稍加修改即可用于你自己的应用程序。
如果你还不熟悉JSP,那么直接从JSP2.0入手是一个不错的主意。但是如果希望学习JSP1.2,也许你需要从JSP教程开始学习。
JSP 2.0
JSP 2.0是对JSP 1.2的升级,增加了几个有趣的新特性,可以使Web应用程序设计人员和开发人员的工作更容易一些。JSP 2.0的目标是比以前更易于使用,更重要的是无须学习Java语言本身就可以使用它。它增加了一种称为SimpleTag的新扩展机制来简化标签API(Tag API)。
除了其他一些改进外,JSP 2.0引入的最主要的新特性包括:
- 一种简单的表达式语言(EL),能够用来容易地从JSP页面访问数据,这种表达式语言简化了基于JSP的不含脚本的应用程序的编写,不需要使用Java Scriptlet或者Java表达式;
- 用于直接使用JSP技术来定义可重用的自定义行为的新语法,该语法使用.tag和.tagx文件,这类文件可由开发人员或者网页作者编写;
- 3XML语法得到了实质性的改进,增加了新的标准文件扩展名(.tagx用于标签文件,.jspx用于JSP文件)。
本文主要讨论表达式语言、简化的标签API和标签文件。相信目前的JSP开发人员将会发现这些重要的特性不但有趣,而且非常有用。
为何要从1.2跨越到2.0?
在Java规格请求(JSR 152)中版本号最初定为1.3。但是正如你将在后面看到的那样,由于这些新特性对JSP应用程序的开发模型产生了如此深刻的影响,专家组感到有必要把主版本号升级到2.0,这样才能充分反映这种影响。此外,新的版本号也有助于把开发人员的注意力吸引到这些有趣的新特性上来。令人欣慰的是,所有合法的JSP1.2页面同时也是合法的JSP2.0页面。
JSP 2.0起步
在着手学习JSP 2.0之前,你需要一个支持JSP2.0和Java Servlet 2.4规范的JSP环境。幸运的是,Jakarta Tomcat 5.0(alpha测试版)支持新的JSP2.0和Servlet 2.4规范,可以从http://jakarta.apache.org/builds/jakarta-tomcat/release/v5.0.4-alpha/下载并安装Tomcat 5.0。
JSP表达式语言
向JSP网页传递信息是通过JSP scoped属性和请求参数完成的。专门为网页作者量身定做的一种表达式语言(EL)把JSP scoped属性提升为从业务逻辑向JSP页面传递信息的标准方式。但是要注意,尽管这种表达式语言是JSP的一个重要特性,它并不是一种通用的程序语言。它仅仅是一种数据访问语言,可以方便地访问和处理应用程序数据,而无需使用scriptlet或者请求时(request-time)表达式的值。
在JSP2.0之前,网页作者只能使用表达式<%= aName %>访问系统的值,比如下面的例子:
<someTags:aTag attribute="<%= pageContext.getAttribute("aName") %>">
或者使用自定义JavaBeans组件的值:
<%= aCustomer.getAddress().getCountry() %>
表达式语言允许网页作者使用简单的语法访问对象。比如要访问一个简单变量,可以像下面这样写:
<someTags:aTag attribute="${aName}">
而访问嵌套的JavaBeans属性,则可以像下面这样写:
${aCustomer.address.country}
你可能会问,这不是JavaScript的语法吗?完全正确!如果你使用过JavaScript,就会感到非常轻松,因为表达式语言正是借用了访问结构化数据的JavaScript语法。
注意:表达式语言最初是作为JSP标准标签库(JSTL)1.0的一部分而开发的,JSTL是一种标准标签库,它提供对通用的、结构化的任务的支持,如迭代和条件、XML文档处理、国际化和利用SQL访问数据库等。JSTL规范是由JSR 52专家组开发的。关于JSTL的介绍,请参见Faster Development with JSTL(使用JSTL加速开发).
访问应用程序数据
可以使用点号运算符(.)访问作为对象属性的应用程序数据,也可使用方括号运算符[‘name’]访问命名的数组元素。
表达式${data}表示名为data的scoped变量。可以使用点号(.)或方括号([])运算符从集合中检索属性值:
- 点号运算符用于访问命名的属性,比如表达式${customer.name}表示scoped变量customer的name属性;
- 方括号运算符可用于检索命名的属性,比如在${customer[“name”]}中。也可以通过${customers[0]}的形式来访问集合customers中的第一项。
表达式语言统一了对点号和方括号运算符的处理,因此${customer.name}与${customer[“name”]}是等价的。正如你看到的那样,表达式必须使用${和}包围起来。
EL的标识符求值方式是使用PageContext.findAttribute(String),把标识符作为一个属性来查找它的值。如果没有找到该属性,则返回null。
运算符
表达式语言支持算术运算符、关系运算符和逻辑运算符,以完成大多数的数据处理操作。此外,它还提供了一个用于测试一个对象是否为空的特殊运算符。运算符如表1所示。你可以使用empty运算符判断某个集合或字符串是否为空。比方说,只有当要求的命名参数param没有给出时,表达式${empty param.name}才返回真。Empty运算符可以与“!”运算符一起使用,比如${!empty param.name}当要求的命名参数param存在时返回真。
表1:表达式语言运算符 | |
运算符 | 说明 |
+ | 加 |
- | 减 |
* | 乘 |
/ 或 div | 除 |
% 或 mod | 模(求余) |
== 或 = | 等于 |
!= 或 != | 不等于 |
< 或 lt | 小于 |
> 或 gt | 大于 |
<= 或 le | 小于等于 |
>= 或 ge | 大于等于 |
&& 或 and | 逻辑与 |
|| or or | 逻辑或 |
! 或 not | 逻辑非 |
empty | 检查是否为空值 |
a ? b : c | 条件运算符 |
隐含对象
除了运算符外,表达式语言还定义了一些隐含对象以支持网页作者访问需要的应用程序数据。表达式语言定义的隐含对象如表2所示,后面将给出使用这些隐含对象的一个例子。
表2:表达式语言中的隐含对象 | |
隐含对象 | 内容 |
applicationScope | 应用程序范围内的scoped变量组成的集合 |
cookie | 所有cookie组成的集合 |
header | HTTP请求头部,字符串 |
headerValues | HTTP请求头部,字符串集合 |
initParam | 全部应用程序参数名组成的集合 |
pageContext | 当前页面的javax.servlet.jsp.PageContext对象 |
pageScope | 页面范围内所有对象的集合 |
param | 所有请求参数字符串组成的集合 |
paramValues | 所有作为字符串集合的请求参数 |
requestScope | 所有请求范围的对象的集合 |
sessionScope | 所有会话范围的对象的集合 |
表达式语言的例子
如你所言,网页作者无须学习Java也能够使用这种表达式语言。示例代码1显示了一些表达式的例子和隐含对象的使用。
代码示例1: ex1.jsp
要运行这个例子,请参照以下步骤,这里我们假定Tomcat 5.0安装在c:/tomcat5.0下。
- 切换目录到 c:/Tomcat5.0/webapps/jsp-examples
- 创建新目录,名字可以是任意的,比如jsp2-tutorial
- 切换到jsp2-tutorial
- 把ex1.jsp复制并保存到该目录下
- 启动Tomcat 5服务器:指向“开始”->“程序”->“Apache Tomcat 5.0”,单击“Apache Tomcat 5.0”来启动Tomcat
- 在浏览器中输入http://localhost:8080/jsp-examples/jsp2-tutorial/ex1.jsp
你将看到类似图1所示的画面。使用表达式语言就这么简单!
图1:JSP表达式语言和隐含对象
注意: 在本文中,所有的JSP文件都保存在c:/Tomcat5.0/webapps/jsp-examples/jsp2-tutorial目录下。
填充表单例子
隐含对象$paran[var]可用于读取填充表单的数据。代码示例2给出了一个简单的表单,该表单提示用户输入一个名字。
代码示例2: form.jsp
<HTML>
<HEAD>
<TITLE>Form Content</TITLE>
</HEAD> <BODY> <H3>Fill-out-form</H3>
<P>
<FORM action="form.jsp" method="GET">
Name = <input type="text" name="name" value="${param['name']}">
<input type="submit" value="Submit Name"> </FORM>
<P>
The Name is: ${param.name}
</BODY>
</HTML>
在本例中,当用户输入名字并单击“提交”按钮时,输入的名字就会显示同一页面中的“The Name is:”字样后面,如图2所示。
同样,运行这个例子只需要把form.jsp复制到c:/Tomcat5.0/webapps/jsp-examples/jsp2-tutorial下并用浏览器打开它。
图2:表单处理
定义和使用函数
表达式语言允许你定义可在表达式中调用的函数。函数必须作为public类中的public static方法编写。函数一经定义,它的签名(signature)就映射到标签库描述符(TLD)中。
为了说明函数的使用,我们举一个简单的例子,把两个数相加。首先要编写求两数之和的Java方法代码,如代码示例3所示,这里定义了一个静态方法,它接收两个字符串参数,把它们解析成整数并返回它们的和。
代码示例3: Compute.java
package jsp2.examples.el;
import java.util.*;
public class Compute {
public static int add(String x, String y) {
int a = 0;
int b = 0;
try {
a = Integer.parseInt(x);
b = Integer.parseInt(y);
}catch(Exception e) {}
return a + b;
}
}
用javac把这段代码编译成功后,下一步就要把函数的签名映射到标签库。代码示例4说明了如何把add函数映射到包含函数实现和函数签名的类。后面将说明把这段代码添加到哪儿。
代码示例4: 函数描述符
<function>
<description>add x and y</description>
<name>add</name>
<function-class>jsp2.examples.el.Compute
</function-class>
<function-signature>int
add(java.lang.String,java.lang.String)
</function-signature>
</function>
现在我们就可以编写一个JSP页面来使用这个函数。代码示例5是包含两个字段的一个表单,用户输入两个数字并按下“求和”按钮,就会调用上面的函数并把两个数相加,结果在同一个页面中显示出来。
代码示例5: math.jsp
<%@ taglib prefix="my"
uri="http://jakarta.apache.org/tomcat/jsp2-example-taglib %>
<HEAD>
<TITLE>Functions</TITLE>
</HEAD>
<BODY>
<H3>Add Numbers</H3>
<P>
<FORM action="math.jsp" method="GET">
X = <input type="text" name="x" value="${param["x"]}">
<BR>
Y = <input type="text" name="y" value="${param["y"]}">
<input type="submit" value="Add Numbers">
</FORM>
<P>
The sum is: ${my:add(param["x"],param["y"])}
</BODY>
</HTML>
要运行这个例子:
- 复制Compute.java并保存到C:/Tomcat5.0/webapps/jsp-examples/WEB-INF/classes/jsp2/examples/el下;
- 使用javac编译Compute.java;
- 编辑文件C:/Tomcat5.0/webapps/jsp-examples/WEB-INF/jsp2/jsp2-example-taglib.tld,把代码示例4中的代码段添加到文件中最后一个</function>标签之后,</taglib>标签之前;
- 复制math.jsp并保存到c:/Tomcat5.0/webapps/jsp-examples/jsp2-tutorial下;
- 用浏览器打开该文件。
如果一切正常,应该会看到类似如图3所示的窗口。
图3:使用函数
标签处理器
JSP 1.2中传统的标签处理API由于允许标签体中包含scriptlet而变得复杂,但是现在利用表达式语言可以编写不含scriptlet的JSP网页。最终,JSP 2.0引入了一种新的标签扩展机制,称为“简单标签扩展”,这种机制有两种使用方式:
- Java开发人员可以定义实现接口javax.servlet.jsp.tagext.SimpleTag的类;
- 不懂Java的网页编写人员则可以使用标签文件。
首先来看第一种方式,代码示例6给出了一个简单的标签处理器,它的作用仅仅是打印“This is my first tag! ”。
代码示例6: HelloTag.java
package jsp2.examples.simpletag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport; import java.io.IOException;
/**
* SimpleTag handler that prints "This is my first tag!"
*/
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
getJspContext().getOut().write("This is my first tag!");
}
}
编译成功后,下一步就要在TLD中定义一个标签描述符,下面是标签描述符的例子。
代码示例7: 标签描述符
<tag>
<description>Prints this is my first tag</description>
<name>hello</name>
<tag-class>jsp2.examples.simpletag.HelloTag</tag-class>
<body-content>empty</body-content>
</tag>
最后再编写一个使用上述标签的JSP页面文件,见代码示例8。
代码示例8: helloworld.jsp
<%@ taglib prefix="mytag" uri="/WEB-INF/jsp2/jsp2-example-taglib.tld" %>
<HTML>
<HEAD>
<TITLE>Simple Tag Handler</TITLE>
</HEAD>
<BODY>
<H2>Simple Tag Handler</H2>
<P>
<B>My first tag prints</B>: <mytag:hello/>
</BODY>
</HTML>
要运行这个例子:
- 复制HelloTg.java并保存到C:/Tomcat5.0/webapps/jsp-examples/WEB-INF/classes/jsp2/examples/simpletag下;
- 使用javac编译HelloTag.java;
- 把代码示例7中的标签描述符添加到文件C:/Tomcat5.0/webapps/jsp-examples/WEB-INF/jsp2/jsp2-example-taglib.tld中的</taglib>之前;
- 复制helloworld.jsp并保存到c:/Tomcat5.0/webapps/jsp-examples/jsp2-tutorial目录中;
- 用浏览器打开helloworld.jsp。
如果一切正常,应该会看到类似如图4所示的画面。
图4:简单标签处理器
标签文件
使用简单标签扩展机制的另一种方法是通过标签文件。标签文件是一种资源文件,网页作者可以利用它抽取一段JSP代码,通过定制功能来实现代码的复用。换句话说,标签文件允许JSP网页作者使用JSP语法创建可复用的标签库。标签文件的扩展名必须是“.tag”。
为说明使用标签文件是多么容易,考虑一下代码示例9。没错,这就是一个标签文件!
代码示例9: greetings.tag
Hello there. How are you doing?
一旦定义了标签文件,就可以在JSP网页的编写中使用这种定制的功能。比如代码示例10中的JSP网页。
代码示例10: chat.jsp
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<HTML>
<HEAD>
<TITLE>JSP 2.0 Examples - Hello World Using a Tag File</TITLE>
</HEAD>
<BODY>
<H2>Tag File Example</H2>
<P>
<B>The output of my first tag file is</B>: <tags:greetings/>
</BODY>
</HTML>
要运行这个例子:
- 复制标签文件greetings.tags并保存在c:/Tomcat5.0/webapps/jsp-examples/WEB-INF/tags 目录下;
- 复制JSP网页文件char.jsp并保存在c:/Tomcat5.0/webapps/jsp-examples/jsp2-tutorial 目录下;
- 用浏览器打开chat.jsp文件。
图5:简单的标签文件
注意: 重要的是要注意到这里没有为问候标签编写TLD,而是创建了一个标签文件并放在特殊的目录中,然后用taglib指令导入并直接使用它。
另一个标签文件的例子
标签文件可以作为模板使用。考虑代码示例11中的标签文件display.tag,这个例子是根据Tomcat 5.0中的面板的例子改写的。指令attribute类似于TLD中的<attribute>元素,允许声明自定义的动作属性。
代码示例11: display.tag
<%@ attribute name="color" %>
<%@ attribute name="bgcolor" %>
<%@ attribute name="title" %>
<TABLE border="0" bgcolor="${color}"> <TR>
<TD><B>${title}</B></TD>
</TR>
<TR>
<TD bgcolor="${bgcolor}">
<jsp:doBody/>
</TD>
</TR>
</TABLE>
代码示例12给出了使用上述标签的一个简单的JSP页面。
代码示例12: newsportal.jsp
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<HTML>
<HEAD>
<TITLE>Another Tag File Example</TITLE>
</HEAD>
<BODY>
<H2>News Portal: Another Tag File Example</H2>
<TABLE border="0"> <TR valign="top">
<TD>
<tags:display color="#ff0000" bgcolor="#ffc0c0"
title="Travel">
Last French Concorde Arrives in NY<br/>
Another Travel Headline<br/>
Yet Another Travel Headline<br/>
</tags:display>
</TD>
<TD>
<tags:display color="#00fc00" bgcolor="#c0ffc0"
title="Technology">
Java for in-flight entertainment<BR>
Another Technology Headline<BR>
Another Technology Headline<BR>
</tags:display>
</TD>
<TD>
<tags:display color="#ffcc11" bgcolor="#ffffcc"
title="Sports">
American Football<BR/>
NBA<BR/>
Soccer<BR/>
</tags:display>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>
要运行这个例子:
- 复制文件display.tag并保存在c:/Tomcat5.0/webapps/jsp-examples/WEB-INF/tag 下;
- 复制文件newsportal.jsp并保存到c:/Tomcat5.0/webapps/jsp-examples/jsp2-tutorial下;
- 用浏览器打开newsportal文件。
结果应该会得到与图6类似的画面。
图6:把标签文件用作模板
结论
JSP 2.0使得快速开发和维护动态网页比以前更加容易,尽管“Java”一词出现在JSP中,但使用JSP2.0,网页作者无须学习Java程序语言本身,就能开发出全新的动态网页。本文中的例子说明了使用JSP2.0的新特性开发动态网页是多么容易。
更多信息
- Fast Track JSP 1.2
- JavaServer Pages Technology
- JavaServer Pages Specification (JSR 152)
- The Tomcat 5 Servlet/JSP Container
- JSP Developers Forum
- JavaServer Pages Standard Tag Library (JSTL)
- Faster Development with JavaServer Pages Standard Tag Library (JSTL 1.0)
致谢特别感谢Sun Microsystems公司的Gregory Murry和Mark Roth,他们的反馈帮助我改进了这篇文章。