JSP简明教程:令人兴奋的脚本编程
如果你是直接使用Java servlets,那你将不得不在Java类中处理HTTP输入和HTML输出,你需要丰富的Java编程经验来构建复杂的应用程序。JSP的加入,使你可以把HTML的表达逻辑从植入servlets中的复杂的商务逻辑区分开来。这意味着可以由有经验的脚本编写者来编写表达层代码,而高级的Java开发者能够集中精力去解决servlets和bean中更为复杂的问题。
不管你有没有Java编程知识,都能够使用JSP。JSP包含了一些服务器端的标签,使得不用写一行Java代码就能显示动态数据。你可以直接访问bean来完成操作,然后使用JSP标签把结果显示为动态内容。你还可以用servlets生成bean,servlets 操作的运算结果存于其中,然后再使用JSP标签显示结果,同样不需要在JSP页中写Java代码。
有三种方式可以用来在你的网页中加入Java代码:
1、使用declarations(声明),可以定义全局变量或是在页内任何地方都可以访问的Java方法。声明被包含在标记<%!...%>中。
2、使用scriptlets(脚本片断),你能书写页内处理所需的任何逻辑,它们包含在<%...%>标记内。
3、Expressions(表达式),包含于<%=...%>中。它提供一种简单的方法来显示Java表达式的结果。被附加上的表达式将被计算并在页面上显示出来,就好像你已经在代码中明确写出了运算结果的数值一样。
在你自己编写的代码中,可以使用一些隐含变量(implicit variables)――JSP提供的预定义的Java对象。另外,通过使用JSP的指令(directives), 还可以包含非Java代码模块,比如来自其他文件的HTML文本。
下面我们来仔细看一看这些脚本元素,在编写你自己的JSP脚本时将会经常用到它们。
Directives(指令)
JSP定义了三个页内指令用于设置JSP参数或扩充代码。它们是 page,include和taglib,必须写在JSP页的第一行。语法如下:
<%@ directive attribute="value" ... %>
page指令允许你为网页设定一些基本参数,包括设置所用脚本语言的参数(默认为Java)、你的脚本片断中引入的Java类、设置输出缓冲区等等。完整的page指令参数表见《JSP Specification Version 1.0》(《JSP规范1.0》)的2.8.1章。
使用include指令,可以包含其他文件的内容,比如存于单独文件中的HTML报头和页脚。
taglib指令用于扩充标准的JSP标签集,这超出了本文的讨论范围。然而,了解JSP定义了一种扩充其标签集的方法还是很有好处的,当你是一个软件商,想扩充JSP的原始功能而又不想破坏其兼容性时,这一点尤为重要。
Declarations(声明)
使用declarations,你可以在JSP页中定义方法或变量,它们可被同一页中的其他代码访问。在大多数情况下,你可能会在自己的bean中定义方法。然而,有时候在网页内定义方法可能更方便一些,尤其是当代码只用于单一页面时。不论定义方法还是变量,声明都包含在<%! %>标记内。
注意,声明并不在JSP页内产生任何输出。它们仅仅用于定义,而不生成输出结果。要生成输出结果,你应该用JSP表达式或脚本片断。
Expressions(表达式)
Expressions是一种非常简单的JSP标签,它用来把在<%= %>中定义的JSP表达式的值转换成字串并将这个值以动态文本的形式送出。Expression的确是一条生成文本的捷径,有了它,你不必在每次要显示一段动态文本的时候都去调用print()方法。典型的应用就是,你可以用expressions显示简单的变量值或bean中的方法的返回值。
例如,下面的代码将会生成getName()方法的返回值:
<H2>Welcome, <%= mybean.getName() %></H2>
事实上,在生成动态输出之前,JSP必须把方法的返回值转变为Java中的String对象。JSP规范中详细描述了在JSP表达式中,什么样的Java类型和Java类会被转变成字串。
Scriptlets(脚本片断)
到现在为止你已经学会了使用指令来引入任何Java类或Java包,你能定义页面级的方法或变量并在页中使用它们,你还可以使用提供普通web处理功能的隐含变量。还能在JSP页内做些什么就取决于你了,因为你可以在scriptlets(脚本片断)里编写任何你想要的Java代码,如下所示:
<% ...code... %>
通过在page指令中使用IMPORT参数,你可以从脚本片断内调用所有Java API。因为你写的所有JSP代码实际上都被编译构成Java servlet,它本身就是一个Java类,所以你所用的语言本身就是Java,而不是任何一种修改或整理过的版本。这就像在SSJS中你可以编写任何代码一样。而与SSJS不同,在JSP中你有权使用整套丰富的Java API,因此几乎没有任何局限性。
Implicit Variables(隐含变量)
前面提到过,JSP定义了一些隐含变量(即Java 对象)供你在表达式和脚本片断中使用。《JSP Specification Version 1.0》的表2-2列出了JSP1.0中可用的隐含变量。这里列出一些常用的对象:
out对象,类型为javax.servlet.jsp.JspWriter,提供对方法(例如print()方法)的访问,用来在脚本片断内生成输出结果。
request对象直接与Java中的javax.servlet.http.HttpServletRequest类对应,具有该类的对象的一切属性和方法。举个例子,要获取一个从HTML表单或URL查询字串传入的值,可以调用request.getParameter()方法,根据名字获取参量。
response对象与Java中的javax.servlet.http.HttpServletResponse类对应,提供对你的网页产生的HTML响应的参数的访问权。因此,要在JSP页返回的HTML响应报头中加入一个值,你就可以调用the response.setHeader() 方法来实现。
另一个简单的例子
在下面的例子中,我们来看一看一个表单和它的JSP表单句柄之间的交互过程。使用前面讨论过的脚本元素,我实现了一个简单的web站点回馈表单(见图2)和一个JSP表单句柄用来验证输入,然后有条件地地生成基于回馈的输出。
图2.一个web站点回馈表单
图中按钮:submit query--提交;reset――重填
表单句柄将会检验名称和意见栏以确定它们已被填写,如果其中任何一个或两个是空白的,表单句柄会生成一条错误信息;否则它将继续查看用户意见是否与预先设定的字串匹配。如果匹配,它就输出一条专门的信息;否则输出thank you。
例2
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="NetObjects ScriptBuilder 2.01">
<TITLE>Feedback Results</TITLE>
</HEAD>
<%!
// 姓名和意见栏不能为空白
// 检查它们的值并返回结果
boolean validateInput(String name, String comment) {
boolean result = true;
// 如果姓名或意见未填写,返回 false 以表明输入无效
if (name.length() == 0)
result = false;
if (comment.length() == 0)
result = false;
return result;
} // 结束输入验证validateInput
// 根据表单上的意见栏输出结果
String getStringCheese (String comment) {
String cheese = "I like cheese.";
String result;
if (comment.compareTo(cheese) == 0)
result = "We like cheese too!";
else
result = "We hope someday youll learn to like cheese.";
return result;
} //结束 getStringCheese
%>
<BODY BGCOLOR="#F0F0E0">
<%
// 获取通过表单提交的数据
String name = request.getParameter("name");
String age = request.getParameter("age");
String comment = request.getParameter("comment");
boolean isValid;
isValid = validateInput(name, comment);
// 根据用户是否未填写姓名或意见栏决定输出内容
if (isValid) {
%>
<H2>Thank you for your feedback!</H2>
<H3>
<%
//输出意见栏的查询结果
out.println(getStringCheese(comment));
} // 结束 if 程序段
else {
out.println("You didnt give us your name or a comment.");
%>
</H3>
Please <a href="feedback_form.html">try again</a>
<%
} //结束 else 程序段
%>
</BODY>
</HTML>
这个例子假定用户输入的意见是I like cheese."(我喜欢奶酪)在代码中可以看到,这一响应是为填写这条意见的用户定制的。表单句柄将会返回如图3所示的页面:
图3.表单句柄输出
图中文字:谢谢你的反馈!我们也喜欢奶酪。
这个例子非常简单易懂。即便你只是一个JavaScript程序员,你也应该可以理解它。我还要指出这个例子中体现的在JSP规范中并不很明显的一些特性。首先,请注意我在声明部分(<%...%>中的部分)定义了一些方法,与在Java类中定义方法一模一样。这是因为JSP引擎把这些方法转变为底层的Java servlets,在浏览器向网页发出请求时由服务器来执行它们。因此,任何变量和方法的定义都必须遵守标准的Java语法。
还应注意到,在我的脚本片断的代码中,我把一个if...else语句分开了,它跨越了两个不同的脚本片断段。这完全是合法的!不仅合法,而且把脚本片断代码和静态HTML交叉起来是有条件生成HTML的好办法,就像我在本例中所做到的一样。
最后,你可以看到我通过调用request.getParameter()方法取得表单元素的值并把它赋给一个临时变量。这是处理从表单或查询字串输入的值的标准方法。
如果你是直接使用Java servlets,那你将不得不在Java类中处理HTTP输入和HTML输出,你需要丰富的Java编程经验来构建复杂的应用程序。JSP的加入,使你可以把HTML的表达逻辑从植入servlets中的复杂的商务逻辑区分开来。这意味着可以由有经验的脚本编写者来编写表达层代码,而高级的Java开发者能够集中精力去解决servlets和bean中更为复杂的问题。
不管你有没有Java编程知识,都能够使用JSP。JSP包含了一些服务器端的标签,使得不用写一行Java代码就能显示动态数据。你可以直接访问bean来完成操作,然后使用JSP标签把结果显示为动态内容。你还可以用servlets生成bean,servlets 操作的运算结果存于其中,然后再使用JSP标签显示结果,同样不需要在JSP页中写Java代码。
有三种方式可以用来在你的网页中加入Java代码:
1、使用declarations(声明),可以定义全局变量或是在页内任何地方都可以访问的Java方法。声明被包含在标记<%!...%>中。
2、使用scriptlets(脚本片断),你能书写页内处理所需的任何逻辑,它们包含在<%...%>标记内。
3、Expressions(表达式),包含于<%=...%>中。它提供一种简单的方法来显示Java表达式的结果。被附加上的表达式将被计算并在页面上显示出来,就好像你已经在代码中明确写出了运算结果的数值一样。
在你自己编写的代码中,可以使用一些隐含变量(implicit variables)――JSP提供的预定义的Java对象。另外,通过使用JSP的指令(directives), 还可以包含非Java代码模块,比如来自其他文件的HTML文本。
下面我们来仔细看一看这些脚本元素,在编写你自己的JSP脚本时将会经常用到它们。
Directives(指令)
JSP定义了三个页内指令用于设置JSP参数或扩充代码。它们是 page,include和taglib,必须写在JSP页的第一行。语法如下:
<%@ directive attribute="value" ... %>
page指令允许你为网页设定一些基本参数,包括设置所用脚本语言的参数(默认为Java)、你的脚本片断中引入的Java类、设置输出缓冲区等等。完整的page指令参数表见《JSP Specification Version 1.0》(《JSP规范1.0》)的2.8.1章。
使用include指令,可以包含其他文件的内容,比如存于单独文件中的HTML报头和页脚。
taglib指令用于扩充标准的JSP标签集,这超出了本文的讨论范围。然而,了解JSP定义了一种扩充其标签集的方法还是很有好处的,当你是一个软件商,想扩充JSP的原始功能而又不想破坏其兼容性时,这一点尤为重要。
Declarations(声明)
使用declarations,你可以在JSP页中定义方法或变量,它们可被同一页中的其他代码访问。在大多数情况下,你可能会在自己的bean中定义方法。然而,有时候在网页内定义方法可能更方便一些,尤其是当代码只用于单一页面时。不论定义方法还是变量,声明都包含在<%! %>标记内。
注意,声明并不在JSP页内产生任何输出。它们仅仅用于定义,而不生成输出结果。要生成输出结果,你应该用JSP表达式或脚本片断。
Expressions(表达式)
Expressions是一种非常简单的JSP标签,它用来把在<%= %>中定义的JSP表达式的值转换成字串并将这个值以动态文本的形式送出。Expression的确是一条生成文本的捷径,有了它,你不必在每次要显示一段动态文本的时候都去调用print()方法。典型的应用就是,你可以用expressions显示简单的变量值或bean中的方法的返回值。
例如,下面的代码将会生成getName()方法的返回值:
<H2>Welcome, <%= mybean.getName() %></H2>
事实上,在生成动态输出之前,JSP必须把方法的返回值转变为Java中的String对象。JSP规范中详细描述了在JSP表达式中,什么样的Java类型和Java类会被转变成字串。
Scriptlets(脚本片断)
到现在为止你已经学会了使用指令来引入任何Java类或Java包,你能定义页面级的方法或变量并在页中使用它们,你还可以使用提供普通web处理功能的隐含变量。还能在JSP页内做些什么就取决于你了,因为你可以在scriptlets(脚本片断)里编写任何你想要的Java代码,如下所示:
<% ...code... %>
通过在page指令中使用IMPORT参数,你可以从脚本片断内调用所有Java API。因为你写的所有JSP代码实际上都被编译构成Java servlet,它本身就是一个Java类,所以你所用的语言本身就是Java,而不是任何一种修改或整理过的版本。这就像在SSJS中你可以编写任何代码一样。而与SSJS不同,在JSP中你有权使用整套丰富的Java API,因此几乎没有任何局限性。
Implicit Variables(隐含变量)
前面提到过,JSP定义了一些隐含变量(即Java 对象)供你在表达式和脚本片断中使用。《JSP Specification Version 1.0》的表2-2列出了JSP1.0中可用的隐含变量。这里列出一些常用的对象:
out对象,类型为javax.servlet.jsp.JspWriter,提供对方法(例如print()方法)的访问,用来在脚本片断内生成输出结果。
request对象直接与Java中的javax.servlet.http.HttpServletRequest类对应,具有该类的对象的一切属性和方法。举个例子,要获取一个从HTML表单或URL查询字串传入的值,可以调用request.getParameter()方法,根据名字获取参量。
response对象与Java中的javax.servlet.http.HttpServletResponse类对应,提供对你的网页产生的HTML响应的参数的访问权。因此,要在JSP页返回的HTML响应报头中加入一个值,你就可以调用the response.setHeader() 方法来实现。
另一个简单的例子
在下面的例子中,我们来看一看一个表单和它的JSP表单句柄之间的交互过程。使用前面讨论过的脚本元素,我实现了一个简单的web站点回馈表单(见图2)和一个JSP表单句柄用来验证输入,然后有条件地地生成基于回馈的输出。
图2.一个web站点回馈表单
图中按钮:submit query--提交;reset――重填
表单句柄将会检验名称和意见栏以确定它们已被填写,如果其中任何一个或两个是空白的,表单句柄会生成一条错误信息;否则它将继续查看用户意见是否与预先设定的字串匹配。如果匹配,它就输出一条专门的信息;否则输出thank you。
例2
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="NetObjects ScriptBuilder 2.01">
<TITLE>Feedback Results</TITLE>
</HEAD>
<%!
// 姓名和意见栏不能为空白
// 检查它们的值并返回结果
boolean validateInput(String name, String comment) {
boolean result = true;
// 如果姓名或意见未填写,返回 false 以表明输入无效
if (name.length() == 0)
result = false;
if (comment.length() == 0)
result = false;
return result;
} // 结束输入验证validateInput
// 根据表单上的意见栏输出结果
String getStringCheese (String comment) {
String cheese = "I like cheese.";
String result;
if (comment.compareTo(cheese) == 0)
result = "We like cheese too!";
else
result = "We hope someday youll learn to like cheese.";
return result;
} //结束 getStringCheese
%>
<BODY BGCOLOR="#F0F0E0">
<%
// 获取通过表单提交的数据
String name = request.getParameter("name");
String age = request.getParameter("age");
String comment = request.getParameter("comment");
boolean isValid;
isValid = validateInput(name, comment);
// 根据用户是否未填写姓名或意见栏决定输出内容
if (isValid) {
%>
<H2>Thank you for your feedback!</H2>
<H3>
<%
//输出意见栏的查询结果
out.println(getStringCheese(comment));
} // 结束 if 程序段
else {
out.println("You didnt give us your name or a comment.");
%>
</H3>
Please <a href="feedback_form.html">try again</a>
<%
} //结束 else 程序段
%>
</BODY>
</HTML>
这个例子假定用户输入的意见是I like cheese."(我喜欢奶酪)在代码中可以看到,这一响应是为填写这条意见的用户定制的。表单句柄将会返回如图3所示的页面:
图3.表单句柄输出
图中文字:谢谢你的反馈!我们也喜欢奶酪。
这个例子非常简单易懂。即便你只是一个JavaScript程序员,你也应该可以理解它。我还要指出这个例子中体现的在JSP规范中并不很明显的一些特性。首先,请注意我在声明部分(<%...%>中的部分)定义了一些方法,与在Java类中定义方法一模一样。这是因为JSP引擎把这些方法转变为底层的Java servlets,在浏览器向网页发出请求时由服务器来执行它们。因此,任何变量和方法的定义都必须遵守标准的Java语法。
还应注意到,在我的脚本片断的代码中,我把一个if...else语句分开了,它跨越了两个不同的脚本片断段。这完全是合法的!不仅合法,而且把脚本片断代码和静态HTML交叉起来是有条件生成HTML的好办法,就像我在本例中所做到的一样。
最后,你可以看到我通过调用request.getParameter()方法取得表单元素的值并把它赋给一个临时变量。这是处理从表单或查询字串输入的值的标准方法。