第3章 JSP语法
【本章专家知识导学】
JSP是建立在Java语言基础上的一种Web程序设计语言,具有自己特有的用法和指令。本章首先介绍JSP页面的程序结构,然后讲述JSP程序中经常用到基本的面向对象Java语言程序基础知识,最后讲在JSP中特有的JSP指令和JSP动作指令。
通过本章的学习,应当深入了解JSP语法,并能灵活运用JSP语法编写简单的JSP页面和其中的Java程序。
3.1 JSP程序的结构
JSP页面的文件名以“.jsp”为后缀,在一个JSP页面中,除了基本的HTML语言元素外,主要还包含三种基本元素:JSP指令、JSP动作指令和JSP代码。JSP指令用于告诉JSP的Web引擎(如Tomcat)需要在编译时做什么动作,比如引入一个其它的类,设置JSP页面使用什么语言编码等。JSP动作指令则是在JSP页面被请求时动态执行的,比如可以根据某个条件动态跳转到另外一个页面。JSP代码指的就是嵌入在JSP页面中的Java代码,即Java程序片,它通常包含JSP表达式、变量和方法的声明以及Java语句。所有HTML文件可以在浏览器中直接打开查看运行效果,但是JSP文件必须先放到Web服务器中,然后通过HTTP的方式访问。
【例3-1】一个简单的JSP程序结构示例
3-1.jsp
<%@ page contentType="text/html;charset=gb2312" %>
<html>
<head><title>
一个简单的JSP程序结构示例
</title></head>
<body>
生成并显示一个从0~9的字符串:
<%! String str="0"; %>
<% for (int i=1; i <10; i++) {
str = str + i;
}
%>
<p> <%= str %>
</p>
</body>
</html>
这个简单JSP页面的基本结构程序包含了三部分:普通的HTML标记、JSP指令和JSP代码。通过一个for语句生成并显示一个从0~9的字符串,程序的执行结果如图3-1所示。
图3-1 一个简单的JSP程序结构示的运行结果
JSP表达式包含一个符合JSP语法的表达式,JSP表达式使用的方法如下:
<%=表达式%>
其中:“<%=”和“%>”之间为JSP表达式,一对表达式标志“<%=”和“%>”中只能有一个表达式。例如:
<%="Hello World!" %>
<%= 1+1 %>
表达式中的变量需要在脚本程序中事先声明,表达式运行后的结果会被自动地转化为字符串,然后插入到这个表达式在JSP文件中的位置,显示在网页上。因为这个表达式的值自动地转化为字符串,所以能在一行文本中插入这个表达式,Web引擎遇到“<%=”符号后,就会把“<%=”和“%>”中的内容作为表达式来解析。
【专家提示】JSP表达式标志不能用一个分号“;”来作为表达式的结束符,但是同样的表达式用在Java脚本代码中就需要以分号来结尾了。
Java脚本代码(Java Scriptlet)是指在JSP页面中的“<%”和“%>”之间插入的Java程序代码。Java脚本代码使用的语法格式如下:
<% Java脚本代码%>
其中“<%”和“%>”之间为Java脚本代码。
“<%”和“%>”是Java脚本代码标志。Java脚本代码中可以包含多个JSP语句、方法、变量、表达式,它可以访问JSP对象、操作数据库、使用Java类库中的类等,利用这些可以在JSP页面内实现较复杂的逻辑功能。有了Java脚本代码,便能做以下的事:
(1)声明将要用到的变量或方法。
(2)编写JSP表达式。
(3)使用任何隐含的对象和任何用<jsp:useBean>声明过的对象。
(4)编写Java语句。
Java脚本代码由服务器负责把它转化成对应的Servlet的Service方法。当JSP服务器收到客户的请求时,Scriptlet就会被执行,如果Java脚本代码中有显示的内容(即向浏览器页面的输出),这些显示的内容就被输出到out对象流中,形成网页的动态部分。
【例3-2】JSP脚本代码示例
3-2.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<%@page language="java" %>
<html>
<head><title> JSP脚本代码示例</title>
</head>
<body>
<h3> Java Scriptlet</h3>
<%
for (int i =1;i <=5;i ++)
{
%>
<p>
i=<%= i %>
</p>
<%
}
%>
</body>
</html>
例3-2是使用循环语句在网页中显示i值(1 2 3 4 5)的JSP页面代码,其中的一个脚本代码段如:<% for (int i =1;i <=5;i ++) { %>。
它不是完整的Java代码语句,但是它和随后的其他脚本代码段一起构成完整的Java脚本代码语句。不同的脚本代码段之间可以按需要添加HTML文本。其运行结果如图3-2。
图3-2 JSP脚本代码示例运行结果
声明变量或方法的语法格式:
<%!声明变量或方法的代码%>
其中:“<%!”和“%>”之间为Java脚本程序声明的变量或方法。声明的代码不产生输出,而只声明了供访问的方法和变量,因此通常要将其和Java表达式、Java脚本程序结合使用。
声明的代码用于声明目标Servlet类的方法和变量(在处理HTTP请求的“service”方法之外)。在程序中也可以一句声明语句声明多个变量和方法,只要以“;”结尾就行。当然这些声明语句要合乎Java语法。
【专家提示】当声明方法或变量时,要注意以下的一些规则:
(1)声明必须以“;”结尾(Java脚本有同样的规则,但是表达式就不同了)。
(2)可以直接在<%@page%>语句中使用声明语句,包含已经声明了的变量和方法,不需要对它们重新声明。
(3)一个声明仅在一个页面中有效。如果想每个页面都用到一些声明,最好把它们写成一个单独的文件,然后用<%@include%>或<jsp:include>语句包含进来。
【例3-3】Java程序片综合应用示例—一个简单的计数器
3-3.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<html>
<body>
<%!int counter=0;
synchronized void counterFunction()
{
counter++;
}
%>
<%counterFunction();%>
网站计数器<br>
您是第<%=counter%>位访问者
</body>
</html>
本例的代码是一个简单的计数器程序,它先后声明了一个计数器变量和计数的方法。计数器变量在客户间共享,直到服务器关闭;而计数方法只做简单的加1处理。Synchronized保留字表示串行化处理,即表示counterFunction()方法在某个时刻只能由一个语句调用。上述程序的其运行的结果如图3-3所示。
图3-3 Java程序片综合应用示例运行结果
Java语言标识符用来表示变量、方法或类等的名字。Java语言标识符的组成规则为:
(1)标识符必须以字母、下划线(_)或美元符($)开头,
(2)标识符第一个字符后面可以跟任意数目的字母、数字、下划线(_)或美元符($)。标识符的长度没有限制。
(3)在声明和使用标识符时需要注意,Java语言是大小写敏感的。
(4)标识符的命名应遵循Java编码惯例,并且应使标识符能从字面上反映出它所代表的变量或类型的用途,但不能是关键字。所有Java关键字都是小写的,true、false、null等都不是Java关键字;goto和const 虽然从未使用,但也作被为Java关键字保留;true、false、null虽用做专门用途,但不是Java关键字。
Java语言的关键字包括9大类:
(1)原始数据类型:byte、short、int、long、float、double、char、boolean。
(2)循环关键字:do、while、for、break、continue。
(3)分支关键字:if、else、switch、case、default、break。
(4)方法、变量和类修饰符:private、public、protected、final、static、abstract、synchronized、volatile、strictfp。
(5)异常处理:try、catch、finally、throw、throws。
(6)对象相关关键字:new、extends、implements、class、instanceof、this、super。
(7)字面值常量:false、true、null。
(8)方法相关关键字:return、void。
(9)包相关关键字:package、import。
(1)常量和变量
常量是指在程序运行过程中其值不变的量。常量有字面常量和符号常量两种。常量在表达式中用文字串表示,它区分不同类型,如整型常量123、-15,实型常量12.1f,字符常量' x ',布尔常量true,字符串类型常量"Test"。而符号常量声明的一般格式如下:
<final> <数据类型> <符号常量标识符>=<常量值>;
例如:final double PI=3.141593;
final int COUNT=1000;
变量是用来存放指定类型的数据,其值在程序运行过程中是可变的。按变量声明的位置Java的变量分为两种:类成员变量和局部变量。变量声明的一般格式如下:
<数据类型> <变量标识符>=<值>
例如 double x=1.2345;
(2)整型数据
Java整型数据多为十进制数形式,也可为八进制或十六进制形式。Java整型数都为带符号数。整型缺省为int型,若为长整型需在数据后加字母l或L。
按照长度分为:byte、short、int、long。int类型最为常用,可满足大多数场合应用的需要,如果需要更大的整数就可以使用long类型。byte类型范围很小,数据范围在-255到+255之间。short类型很少用,限制数据的存储为先高字节,后低字节,有时会引发错误,不提倡使用。
例如:byte b; short s;
int i; long l;
(3)实型数据
实型用十进制数形式表示,由数字和小数点组成,例如:3.25。也可以用科学计数法形式表示,例如,123E-3。数后加f或F为float,加d或D为double,没有后缀修饰的则缺省为double类型。
实型变量按长度分为:float和double。双精度浮点型double比单精度浮点型float的精度更高,表示数据的范围更大,详见表3-1。
例如,float c;
double d;
(4)字符型数据
字符型常量是用单引号括起来的一个字符,如:'J'、'*'。Java中的字符型数据是16位的Unicode字符,汉字和英文字母占的内存空间相同。如“JAVA你好”共12个字节。
变量的声明如下:
char ch='c';
Java中有以反斜杠(\)开头的字符,反斜杠将其后面的字符转变为另外的含义,称为转义字符。
表3-2 转义字符
【专家提示】字符串常量是使用双引号括起来的字符序列,注意,最后字符不是“\0”,这与C语言中不同。例如:"Let’s learn Java! "。Java中的字符串变量是作为对象来处理的,通过String和StringBuffer类的构造方法来声明,后续内容中还会有详细的介绍。
(5)布尔型数据
布尔型常量值只有2个:true和false。布尔型变量为boolean类型,取值为true或false。
例如:
boolean b=true;
(6)类型转换
整型、实型、字符型数据可以混合运算。运算过程中,不同类型的数据会自动转换为同一类型,然后进行运算。自动类型转换的规则是,低优先级的数据自动会转换为高优先级的数据。
而优先级高的数据类型要转换成优先级低的数据类型,需要用到强制类型转换。其一般形式为:
(类型名)表达式 或
类型名(表达式)
例如:double d=3.14159d;
int a=(int)d;
【例3-4】简单数据类型应用示例
3-4.jsp
<%@ page contentType="text/html;charset=gb2312"%><!--JSP指令标签-->
<%@ page import="java.util.*"%> <!--JSP指令标签-->
<html><!--HTML标记符-->
<body>
<%//以下为Java程序片
boolean booleanTemp=true;
byte byteTemp=100;
char charTemp='x';
int intTemp=234;
short shortTemp=456;
long longTemp=12345678;
int changlong=(int)longTemp;
float floatTemp=1.234F;
double changfloat=floatTemp;
double doubleTemp=1.23E-8;
out.println("布尔变量booleanTemp值为:"+booleanTemp+"<br>");
out.println("字符型变量charTemp值为:"+charTemp+"<br>");
out.println("整型变量intTemp值为:"+intTemp+"<br>");
out.println("短整型变量shortTemp值为:"+shortTemp+"<br>");
out.println("字节型变量byteTemp值为:"+byteTemp+"<br>");
out.println("长整型变量longTemp值为:"+longTemp+"<br>");
out.println("强制类型转化changlong 值为:"+changlong+"<br>");
out.println("单精度型变量floatTemp值为:"+floatTemp+"<br>");
out.println("自动类型changfloat值为:"+changfloat+"<br>");
out.println("双精度型变量doubleTemp值为:"+doubleTemp+"<br>");
%>
</body><!--HTML标记符-->
</html>
</body>
</html>
简单数据类型应用示例程序声明了几个简单数据类型,对其中的几个进行了自动转换和强制转化,并输出所有的值。其运行结果如图3-5所示。
图3-5 简单数据类型应用示例运行结果
数组是相同类型的数据元素按顺序组成的一种复合数据类型,元素在数组中的相对位置由下标来指定。数组中的每个元素通过数组名加下标进行引用。
(1)一维数组
一维数组的声明格式如下:
数组类型 数组名[ ] ;
或
数组类型[ ] 数组名;
数组类型可以是Java中的任何数据类型。数组名必须符合标识符声明规则。“[]”指明该变量是一个数组类型的变量,可放到数组名后面,也可放到数组名前。
在说明数组时,如果不直接指出数组中元素的个数(即数组长度),则在数组说明之后尚不能立即被访问,还需要使用new操作来构造数组,为数组元素分配内存空间,同时对数组元素进行初始化。其格式如下:
数组名=new类型[数组长度];
如:
int student[ ];
student=new int[10];
或
int student[]=new int[10];
数组初始化就是为数组元素指定初始值。用new关键字为一个数组分配内存空间后,系统将为每个数组元素都赋予一个缺省的初值,所有数值型数组元素的初值为0,字符型数组元素的初值为一个不可见的ISO控制符(\u000),布尔型数组元素的初值为false,字符串数组和所有其他对象数组在构造时元素的初值为null。数组一旦创建之后,就不能再改变其长度。但在许多情况下,并不希望数组的初始值为默认值,此时,就需要用赋值语句来对数组的每个元素赋值进行初始化。
数组的初始化还有一种方式是像初始化简单类型一样自动初始化数组,即在声明数组的同时进行初始化,这个时候不需要使用new关键字。例如
int a[ ]={1,2,3,4,5};
【专家提示】注意数组的下标的取值范围从0开始,一直到“数组的长度减1”。例如
int a[]=new int[10];
int b=a[0]+a[9];
数组下标为从0到9。如果调用了a[10],程序运行时将提示越界错误:
java.lang.ArrayIndexOutOfBoundsException
(2)二维数组
在Java中并不直接支持多维数组,所以,多维数组的声明是通过对一维数组的嵌套形式声明来实现的,即用“数组的数组”来声明多维数组。例如,二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。二维数组的声明、初始化和引用与一维数组基本相同,只是二维数组比一维数组多了一个下标。例如:
int a[][]=new int[3][2];
int b[][]={{1},{2,3},{4,5,6}};
数组a被声明为一个3行2列的二维整数数组,并分配存储空间,所有的数据元素都初始化为0;数组b声明了一个3行3列的二维整数数组,并同时给每个数据元素赋初值。
【例3-5】数组应用示例
3-5.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head>
<title>
数组应用示例
</title>
</head>
<body>
<%
int a[][]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
int b[][]=new int[3][4];
int i,j'
System.out.println("数组a各元素的值为:");
for (i=0;i<4;i++){
for(j=;j<3;j++)
System.out.print(a[i][j]+"\t");
System.out.println();
}
for(i=0;i<4;i++)
for(j=0;j<3;j++)
b[j][i]=a[i][j]; //矩阵转置
System.out.println("数组b各元素的值为:");
for(i=0;i<=3;i++){
for(j=0;j<4;j++)
System.out.print(b[i][j]+"\t");
System.out.println();
}
%>
<html>
<body>
上述代码声明了一个二维整数数组a,输出数组a的所有元素,然后把数组a转置成数组b,并输出数组b的所有元素。程序在浏览器中的运行结果如图3-6所示。
图3-6 数组应用示例运行结果
算术运算符用于对整型数和实型数的运算。如:+(加,取正值)、-(减,取负值)、++ (自加)、--(自减)以及+(加)、-(减)、*(乘)、/(除)、%(取余数或取模)。
【专家提示】其中运算符++、--可以位于操作数的前面,如++x 或--x,也可以位于操作数的后面,如x++、x--。无论运算符++、--位于操作数的前面或后面,操作数完成其运算并把结果赋于操作数变量。但是注意,如把++x或x++整体参加表达式运算时,表达式的运算结果可能不同。
后缀++:变量首先进行操作再自身进行加1运算。y= x++等价于:
y= x;
x=x+1;
例如:
int a=2;
int b=a++;
运算结果:a=3,b=2
前缀++:变量自身首先加然后再进行操作。y=++x等价于:
x=x+1;
y= x;
例如:
int a=2;
int b=++a;
运算结果:a=3,b=3
【例3-6】算术运算符应用示例
3-6.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head><title>算术运算符应用示例</title></head>
<body>
<%
int a=10;
out.println("a="+a+"<br>");
int b=++a;
out.println("a="+a+"<br>");
out.println("b="+b+"<br>");
int c=a++;
out.println("a="+a+"<br>");
out.println("c="+c+"<br>");
int d=--a;
out.println("a="+a+"<br>");
out.println("d="+d+"<br>");
int e=a--;
out.println("a="+a+"<br>");
out.println("e="+e+"<br>");
%>
</body>
</html>
上述程序代码对运算符++、--的前缀和后缀算术符的运算结果进行了比较,其运行结果如图3-7所示。
图3-7 算术运算符应用示例运行结果
布尔逻辑运算符有六个,它们是:!(非)、&(与)、&&(简洁与)、|(或)、||(简洁或)、^(异或)。这些运算符要求的操作数和结果值都是布尔型。
【专家提示】注意区别简洁与&&(或||)和非简洁与&(或|):&&,如果其前面的表达式为假,则不再计算其后面的表达式,整个表达式为false;而&,不管其前面的表达式为什么,都计算其后面表达式。例如,
int a=6,b=8,c=10,d=12;
boolean x=++a>b++&&c++>d--;
(a=7,b=9,c=10,d=12,x=false)
boolean x=++a>b++&c++>d--;
(a=7,b=9,c=11,d=11,x=false)
两个表达式x都为false,但它们最后的c、d的值不一样。
包括if-else和 switch两种形式。
(1)if-else 结构
If-else 结构的控制逻辑如图3-8。语句的执行过程是:首先计算布尔表达式,若布尔表达式的值为true,则程序执行语句1,否则执行语句2,然后执行if语句的后续语句。
图3-8 if-else语句的流程图
if-else 结构选择控制语句其格式为:
if (条件) {
语句1;
}else{
语句2;
}
【专家提示】在使用if-else 结构选择控制语句应该注意:
else子句不能作为语句单独使用,它必须是if语句的一部分,与if配对使用。
语句1、语句2后一定要有“;”号。
语句1和语句2可以是复合语句。
if-else 结构选择控制语句可以嵌套使用,这时要注意花括号“{}”匹配问题,当分支较多时建议采用switch 结构,这样程序代码可读性更强一些。
(2)switch 结构
switch语句根据表达式的结果来执行多个可能操作中的一个,其控制逻辑如图3-9所示。语句的执行过程是:switch语句将表达式的值依次与每个case子句中的常量值相比较。如果匹配成功,则执行该case子句中常量值后的语句;如果没有找到,则执行default语句,直到遇到break语句为止退出switch语句。
图3-9 switch语句流程图
switch语句的语法形式如下:
switch (表达式){
case 常量1:
语句1
[break;]
case 常量2:
语句2
[break;]
…
case 常量n:
语句n
[break;]
[default: ]
缺省处理语句
[break;]
}
switch语句中的每个“case 常量n:”称为一个case子句,代表一个case分支的入口。
switch语句中表达式必须为byte,short,int或char类型,常量值必须是与表达式类型兼容的特定的一个常量,不允许有重复的case值。
通过if-else语句可以实现switch语句所有的功能。但通常使用switch语句更简练,且可读性强,程序的执行效率也高。
if-else语句可以基于一个范围内的值或一个条件来进行不同的操作,但switch语句中的每个case子句都必须对应一个单值。
【例3-7】选择控制应用示例
3-7.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head><title>
选择控制应用示例
</title></head>
<body>
2003年6月有多少天?
<%
int month = 6;
int year = 2003;
int numDays = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if((year%4 ==0)&&(year%100 ==0)||(year%400==0))
numDays = 29;
else
numDays = 28;
break;
}
out.print("<br/>");
out.println("答:2003年6月有 "+ numDays+"天。");
%>
</body>
</html>
上述程序代码通过switch语句根据给的年、月,输出该月的天数。其程序运行结果如图3-10所示。
图3-10 选择控制应用示例运行结果
循环语句的作用是反复执行同一段代码直到满足结束条件。许多问题中需要用到循环控制。Java循环语句有while、do-while和for三种。
(1)while 循环
while语句形式如下:
while (布尔表达式) <语句>;
其中:
while是while语句的关键字;布尔表达式是循环条件;语句为循环体,当循环体为多个语句时构成复合语句。
while语句执行的过程为:首先判断布尔表达式的值,当布尔表达式的值为true,则执行循环体,然后再判断条件,直到布尔表达式的值为false,停止执行语句。
【专家提示】使用while语句应注意以下两点:
(1)该语句是先判断后执行,若一开始条件就不成立,则不执行循环体。
(2)在循环体内一定要有改变条件的语句,否则是死循环。
while语句的流程图如图3-11所示。
图3-11 while语句的流程图
(2)do-while循环
Java还提供了另一个与while语句类似的语句——do-while语句。do-while语句的语法形式如下:
do
语句;
while(布尔表达式);
do-while语句执行的过程为:先执行一次循环体中的语句,然后测试布尔表达式的值,如果布尔表达式的值为true,则继续执行循环体。do-while语句将不断地测试布尔表达式的值并执行循环体中的内容,直到布尔表达式的值为false为止。do-while语句的流程图如图3-12所示。
图3-12 do-while 语句的流程图
do-while语句和while语句的不同之处:do-while语句总是先进入循环,然后检测条件,再决定是否继续循环,而while语句是先测试条件,再判定是否进入循环。所以,用do-while语句时,循环体至少执行一次。
(3)for 循环
图3-13 for语句的流程图
for语句是循环的另一种表示形式。for语句的语法形式为:
for(变量初始化表达式1;条件表达式2;对变量的值作递增或递减处理) {
语句组;
}
for是for语句的关键字,语句组为for语句的循环体。
for语句中循环控制变量必须是有序类型,常用的有整型、字符型、布尔型。循环控制变量初值和终值通常是与控制变量类型相一致的一个常量,也可以是表达式。循环次数由初值和终值决定。
for语句的执行过程如图3-13:
(1)按表达式1将初值赋给循环控制变量。
(2)按表达式2判断循环是否成立,即判断控制变量的值是否越过终值(未越过终值为条件成立,越过终值为条件不成立),若条件不成立,则转步骤(6)。
(3)若条件成立,则执行循环体。
(4)按表达式3修改控制变量。对于递增型为原控制变量值的后续;对于递减型为原控制变量值的前导。
(5)返回步骤(2)。
(6)结束循环。
【例3-8】循环应用综合示例
3-8.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head><title>循环应用示例
</title></head>
<body>
<%
int sum,i;
i = 1;
sum = 0;
while (i<=2000) {
if(i%2!=0)
sum+=i;
i++;
}
out.println("用while循环求2000内的奇数和:" +sum);
out.print("<br/>");
i = 1;
sum = 0;
do{
sum+=i;
i+=2;
}while (i<=2000);
out.println("用do-while循环求2000内的奇数和:"+sum);
out.print("<br/>");
for(sum=0,i=1;i<=2000;i+=2)
sum+=i;
out.println("用for循环求2000内的奇数和:"+sum);
out.print("<br/>");
%>
</body>
</html>
上述程序代码用while、do-while和for语句分别求2000内的奇数的和。从代码上看while和do-while语句查不多,只是do-while至少会执行一次,而while却不一定。for语句使用简单明了,使用灵活,经常被程序员所使用。其程序运行结果如图3-14所示。
图3-14 选择控制应用示例运行结果
类是一种复杂的数据类型,它描述了一类对象的属性和行为。类是对象的抽象,对象是类的实例化,要进行面向对象Java程序设计,先要定义类,然后创建对象,再使用对象。来看下面的代码示例。
Class MyDateClass {
private int day;
private int month;
private int year;
public MyDateClass(){
day = 1;
month = 1;
year = 1900;
}
public MyDateClass(int d,int m,int y){
day = d;
month = m;
year = y;
}
public void display(){
System.out.println(day + "-" + month + "-" + year);
}
public static void main(String args[]){
MyClass m1 = new MyDateClass();
MyClass m2 = new MyDateClass(25,12,2005);
m1.display();
System.out.println("m2 是 "+m2.year+"年");
m2.display();
}
}
类的定义要使用关键词class,类体包括数据和操作两部分。数据是类的成员变量,表示对象的属性;操作是类的成员方法,表示对象的行为。在上面的例子中定义了一个MyDateClass类,有day、month、year3个数据,以及MyDateClass()和display()方法,在main(String args[])方法中通过new声明和创建了两个实例对象m1、m2。在Java中所有的对象的内存空间都是动态分配的,所以要用new运算符声明和创建它们。对象的使用通过运算符“.”可以实现对象的成员变量和成员方法的使用,m1.display()和m2.display()是对成员方法的调用,而m2.year是对成员变量的访问。
从MyDateClass()、display()和main(String args[])方法,可以看出类的方法代码编写格式为:
返回的数据类型 方法名 ([参数列表]){
//方法体,实现对象的行为的代码
}
其中MyDateClass()和MyDateClass(int d,int m,int y)两个方法与类MyDateClass同名,称之为构造函数。构造函数名称与类名称相同,构造函数没有返回类型,其任务是在创建对象时初始化其内部状态。如果类中没有定义构造函数,则表示默认有一个无参数构造方法。MyDateClass()和MyDateClass(int d,int m,int y)两个方法同名,只是参数列表中参数个数和类型不同,这就是所谓的方法重载。
被继承的类称为父类,继承父类的类称为子类。执行继承时,子类将获得父类的属性,并具有自身特有的属性。extends关键字用于继承类,声明一个继承父类的类的通常形式如下:
class 子类名 extends 父类名 {
//子类程序代码
}
如果类的声明中在没有extends,则默认父类为Object。Java语言中子类只能有一个父类,具有单继承性,要用到多继承时可以通过后文中讲解的接口来实现。
class A{
int value = 3;
int getValue(){return value;}
}
class B extends A{
int value = 6;
int getValue() {return value;}
int getValue2(){return super.value;}
int getValue3(){return getValue();}
int getValue4(){return super.getValue();}
}
A类是父类,B类是子类,B类继承了A类的数据和方法,同时也增加了一个数据和四个方法。在B类中还用到了关键字super。super指这个对象的父类,关键字super可用于访问父类中定义的属性,调用父类中定义的成员方法,在子类构造方法中调用父类的构造方法。以上程序表示使用父类的构造方法生成实例,super必须是子类构造方法的第一条语句。
用abstract关键字来修饰一个类时,该类叫做抽象类;抽象类必须被继承。抽象类不能被直接实例化,它只能作为其它类的超类,这一点与最终类(final类)正好相反。
用abstract来修饰一个方法时,该方法叫做抽象方法。抽象方法只有声明,不能有实现。抽象方法必须被重写。定义了抽象方法的类必须是抽象类。下面是一个抽象类的例子。
abstract class Shape{
abstract float area( );
}
class Circle extends Shape{
public float r;
Circle(float r){
this.r = r; //this指“这个对象的”
}
public float area( ){
return 3.14*r*r;
}
}
抽象类Shape中声明了一个抽象方法area( ),该方法在子类中实现。
Java提供了丰富的标准类来帮助程序员更方便快捷地编写程序,这些标准类组成了类包,主要有:
(1)java.lang
本类包中的类构成Java语言核心的类,任何java程序都将自动引入这个包。其中的类包括:
Object类:java中最原始、最重要的类,每个java类都是它的子类,它实现了每个类都必须具有的基本方法。
基本数据类型的包装类:Boolean、Character、Number、Double、Float、Integer、Long。
String类:字符串类。
Math类:数学函数的集合。
执行线程:Thread类、ThreadGroup类、Runable接口。
异常和错误:Exception类、Error类、Throwable接口。
运行环境相关类:还可以通过Runtime类和System类访问外部系统环境。System类的两个常用功能就是访问标准输入/输出流和错误流、退出程序。
其他类:接口Cloneable、运行时的类等。
(2)java.applet
java.applet类包提供了Applet的运行机制以及一些编写Applet非常有用的方法。
(3)java.awt
此本类包是各种窗口环境的统一界面AWT(Abstract Windows Toolkit,即抽象窗口工具包),其中的类使得程序员创建诸如窗口、菜单、滚动条、文本区、按钮以及复选框等图形用户界面(GUI)的元素变得非常容易。
(4)java.awt.image
该类包中的类能够以独立于设备的方式加载并过滤位图图象。
(5)java.awt.peer
java.awt.peer是全部awt组件的对等对象接口的集合法,awt使用这些方法来实现GUI,而不必关心是何种机器或操作系统。
(6)java.io
Java的输入/输出模式是完全建立在流的基础之上的。流是一种字节从一个地方到另一个地方的单向流动,可以把流附加于文件、管道和通信链路等。java.io类包中定义的许多种流类通过继承的方式进行组织,其中也包括一些用来访问本地文件系统上的文件的流类。
(7)java.net
java.net类包用来完成与网络相关的功能:URL、WWW连接以及更为通用的Socket网络通信。
(8)java.util
java.util类包包含了一些实用类和有用的数据结构,如字典(Dictionary)、散列表(Hashtable)、堆栈(Stack)、向量(Vectro)以及枚举类(Enumeration)等。
所谓包装类,就是可以直接将简单类型的变量表示为一个类。Java共有六个包装类,分别是Boolean、Character、Integer、Long、Float和Double,从字面上我们就可以看出它们分别对应于简单数据类型中的 boolean、char、int、long、float和double。
简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:
Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)
而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据。利用这种方法,也可以实现不同数值型变量间的转换,例如,对于一个双精度实型类,intValue()可以得到其对应的整型变量,而doubleValue()可以得到其对应的双精度实型变量。
在进行简单数据类型之间的转换(自动转换或强制转换)时,总是可以利用包装类进行中间过渡。一般情况下,首先声明一个变量,然后生成一个对应的包装类,就可以利用包装类的各种方法进行类型转换了。例如,当希望把float型转换为double型时:
float f1=100.00f;
Float F1=new Float(f1);
double d1=F1.doubleValue();
【例3-9】包装类示例
3-9.jsp
<%@ page contentType="text/html;charset=gb2312"%><!--JSP指令标签-->
<%@ page import="java.util.*"%> <!--JSP指令标签-->
<html><!--HTML标记符-->
<body>
<%//以下为Java程序片
boolean booleanTemp=true;
Boolean BooleanTemp=new Boolean(false);
byte byteTemp=80;
Byte ByteTemp=new Byte(byteTemp);
char charTemp='c';
Character CharacterTemp=new Character(charTemp);
int intTemp=234;
Integer IntegerTemp=new Integer(intTemp);
short shortTemp=235;
Short ShortTemp=new Short(shortTemp);
long longTemp=1234567;
Long LongTemp=new Long(longTemp);
float floatTemp=1.234F;
Float FloatTemp=new Float(floatTemp);
double doubleTemp=1.23E-8;
Double DoubleTemp=new Double(doubleTemp);
out.println("布尔型包装对象BooleanTemp值为:"+BooleanTemp.booleanValue()+"<br>");
out.println("字符型包装对象CharacterTemp值为:"+CharacterTemp.charValue()+"<br>");
out.println("整型变包装对象IntegerTemp值为:"+IntegerTemp.intValue()+"<br>");
out.println("短整型包装对象ShortTemp值为:"+ShortTemp.shortValue()+"<br>");
out.println("字节型包装对象ByteTemp值为:"+ByteTemp.byteValue()+"<br>");
out.println("长整型包装对象LongTemp值为:"+LongTemp.longValue()+"<br>");
out.println("单精度型包装对象FloatTemp值为:"+FloatTemp.floatValue()+"<br>");
out.println("双精度型包装对象doubleTemp值为:"+doubleTemp+"<br>");
%>
</body><!--HTML标记符-->
</html>
上述代码主要应用了包装类进行数据转换,其运行的结果如图3-15所示。
图3-15 包装类应用示例
String类用来表示字符串常量,用它创建的每个对象都是字符常量,一经建立就不能修改。创建String的一个对象并进行初始化,需要调用类String的构造方法,主要有以下创造方法:
String(String s):通过String对象或字符串常量传递给构造方法。
String(char value[]):将整个字符数组赋给String构造方法。
String(char value[],int offset,int count):将字符数组一部分赋给String构造方法,offset 为起始下标,count为字符数组从offset开始的字符个数。
String类的方法比较多,主要有以下几种:
(1)求字符串长度
public int length( ):返回字符串长度。
(2)字符串比较
public boolean equals(Object anObject):比较两个字符串对象,相等返回true,反之,返回false。
public int compareTo(String s):比较两个字符串的字典顺序,相等返回0,s大于当前串返回一个负值,s小于当前串返回一个正值。
public boolean startsWith(String prefix):从当前字符串的起始位置开始寻找字符串prefix。看当前字符串是否以prefix开头,如发现匹配,返回true,否则,返回false。
public boolean endsWith(String suffix):如当前字符串的结尾子串与suffix匹配,返回true,否则,返回false。
boolean regionMatches(int toffset,String other,int ooffset,int len):从当前字符串位置toffset开始寻找字符串other中起始位置为ooffset、长度为len的子串。如发现匹配,返回true,否则,返回false。
(3)字符串的检索和求子串
public char charAt(int index):返回当前字符串位置index处的字符。
public int indexOf(String str):在当前字符串中寻找与str匹配的子串,返回首次匹配的起始下标值,无匹配返回-1。
public String substring(int beginIndex,int endIndex):在当前字符串中,求从起始位置beginIndex到结束位置endIndex的子串。
【例3-10】String类字符串的检索和求子串应用示例
3-10.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head>
<title>String类字符串的检索和子串应用示例</title>
</head>
<body>
<%
String str="I like JSP programming!";
int il=str.indexOf('J');
String s1=str.substring(il);
String s2=str.substring(il,il+4);
int i2=str.lastIndexOf('J');
String s3=str.substring(i2-5);
out.println("s1="+s1);
out.print("<br/>");
out.println("s2="+s2);
out.print("<br/>");
out.println("s3="+s3);
%>
</body>
</html>
上述程序代码应用了String类的检索方法和求子串的方法,修改后的字符串存储在新的String类字符串对象中。该程序运行结果如图3-17所示。
图3-17 String类字符串的检索和求子串应用示例运行结果
(4)字符串的修改
public String toLowerCase():将当前字符串中的字符全部转换为小写形式。
public String toUpperCase():将当前字符串中的字符全部转换为大写形式。
public String replace(char oldChar,char newChar):将字符newChar替换当前字符串中所有的字符oldChar,并返回替换后的新字符串。
public String concat(String str):将当前字符串与str连接,返回连接后的字符串。
(5)字符串类与其他类型的转换
public Static String valueOf(type variable) 把variable转换为字符串。
public String toString():把一个对象转化为String类型。
【例3-11】String类字符串的综合应用示例
3-11.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head>
<title>
String类字符串的综合应用示例
</title>
</head>
<body>
<%
String s1="Hello Java!";
String s2="GOOD!";
out.println("字符串s1为:"+s1);
out.print("<br/>");
out.println("字符串s1的长度为:"+s1.length());
out.print("<br/>");
out.println("字符串s1的大写形式为:"+s1.toUpperCase());
out.print("<br/>");
out.println("字符串s2的小写形式为:"+s2.toLowerCase());
out.print("<br/>");
for(int i=0; i<s1.length(); i++){
out.println("s1中的第"+ i +"个字符是:"+s1.charAt(i));
out.print("<br/>");
}
out.println("s1+s2="+s1+s2);
out.print("<br/>");
if(s1.compareTo(s2)= =0)
out.println("字符串s1与s2相等");
else
out.println("字符串s1与s2不相等");
out.print("<br/>");
if(s1.indexOf(s2)!=-1){
out.println("字符串s2是s1的子串");
out.print("<br/>");
out.println("字符串s2在s1中的位置是:"+s1.indexOf(s2));
}
else
out.println("字符串s2不是s1的子串");
out.print("<br/>");
out.println("经过上述操作:");
out.print("<br/>");
out.println("字符串s1仍然为:"+s1);
out.print("<br/>");
out.println("字符串s2仍然为:"+s2);
%>
</body>
</html>
上述程序代码使用String类的修改方法对原有的字符串进行修改,修改后的字符串存储在新的String类字符串对象中,原有的字符串对象不变。其程序运行结果图3-18所示。
图3-18 String类字符串的综合应用示例
String类的实例用于表示不能改变的静态字符串,StringBuffer类的实例却用来代表动态可变的字符串。StringBuffer类还可以用于创建String类,StringBuffer一旦建立,即可用toString()方法将其转换为String类。
StringBuffer类的构造函数有以下的形式:
(1)StringBuffer():创建默认的空字符串对象,缓冲区大小为16个字符。
(2)StringBuffer(int len):建立缓冲区大小为len的字符串对象。
(3)StringBuffer(String str):创建一个初始化为str的字符串对象。
StringBuffer类的主要方法有如下的几类:
(1)分配/获取字符串的长度
void setLength(int newLength):指定字符串的长度。
int length():返回缓冲区的字符个数,即字符串的长度。
(2)分配/获取字符串的容量
void ensureCapacity(int minCapacity):分配字符缓冲区的大小,分配的字符缓冲区的容量至少为指定的值minCapacity。如果当前的缓冲区容量小于minCapacity,则应该分配较大的缓冲区。
int capacity():返回缓冲区剩余空间。
【专家提示】长度length和容量capacity是两个不同的概念,长度是指StringBuffer类对象中包含字符的个数,而容量是只缓冲区的大小。
(3)字符串的检索和子串
void getChars(int srcBegin,int srcEnd,char[] dst,int dstBegin):将StringBuffer对象字符串中的字符复制到目标数组中去。
public String substring(int beginIndex,int endIndex):当前StringBuffer类字符串中,求从起始位置beginIndex到结束位置endIndex的子串。
(4)字符串的修改
public synchronized StringBuffer append(type variable):把variable转换为字符串,然后与当前字符串连接。
StringBuffer insert(int index,String str):将一个字符串str从当前字符串的index位置开始插入到当前StringBuffer类字符串对象中。
StringBuffer delete(int starts,int end):当前StringBuffer类字符串从starts开始到end-1位置删除子字符串,并返回当前StringBuffer类字符串。
StringBuffer deleteCharAt(int index):删除当前StringBuffer类字符串index处的字符。
StringBuffer reverse():对StringBuffer类字符串进行翻转。
StringBuffer replace(int starts,int end,String str):将字符串str替代当前缓冲字符串的starts开始到end-1位置的子字符串。
void setCharAt(int index,char ch)设置指定位置index处的字符为ch。
(5)字符串类型转换
toString():把StringBuffer转换为字符串String。
【例3-12】Stringbuffer类字符串的综合应用示例
3-12.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<html>
<head>
<title>
Stringbuffer类字符串的综合应用示例
</title>
</head>
<body>
<%
StringBuffer s=new StringBuffer("Hello");
out.println("s:"+s);
out.print("<br/>");
out.println("字符串s的长度:" +s.length());
out.print("<br/>");
out.println("字符串s的容量:"+ s.capacity());
out.print("<br/>");
s.append("Stringbuffer");
out.println("向字符串s中加入了字符串Stringbuffer:"+s);
out.print("<br/>");
out.println("字符串s的位置4-5的子串:"+s.substring(3,5));
out.print("<br/>");
out.println("字符串s的第6个字符:"+s.charAt(5));
out.print("<br/>");
out.println("将字符串的位置6-15的子串替换为java:"+s.replace(5, 16, "java"));
%>
<html>
<body>
上述程序代码首先创建初始化了的StringBuffer对象s,然后显示这个字符串,求其容量和长度,然后在字符串s后追加一个字符串“lo”,并用一个新的字符串替代s的子字符串。其运行结果如图3-19所示。
图3-19 Stringbuffer类字符串的综合应用示例运行结果
在Java中日期型数据处理用Date类,即日期类。Date类构造函数的常用的有四种形式:
(1)Date()
(2)Date(int year, int month, int date):以int型表示年、月、日。
(3)Date(int year, int month, int date, int hrs, int min):以int型表示年、月、日、时、分。
(4)Date(int year, int month, int date, int hrs, int min, int sec):以int型表示年、月、日、时、分、秒。
在长整型和Date类之间有一个对应关系,就是将一个时间表示为距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。对于这种对应关系,Date类也有其相应的构造函数:Date(long date)。
获取Date类中的年、月、日、时、分、秒以及星期读者可以使用Date类的getYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getDay()方法。
而Date类的getTime()方法可以得到前文中所说的一个时间对应的长整型数,与包装类一样。此外,Date类也有一个toString()方法可以将其转换为String类。
【例3-13】日期型数据处理示例
3-13.jsp
<%@ page import="java.util.*" %>
<%@ page contentType="text/html; charset=gb2312" %>
<HTML>
<head><title>日期型数据处理示例</title></head>
<BODY>
你好,今天是
<%
Date today=new Date();
%>
<%=today.getDate()%>号,
星期<%=today.getDay()%>
<h1>现在是北京时间: <%=today.toString() %>
</h1>
</BODY>
</HTML>
在Java中日期型数据处理用Date类,即日期类。Date类构造函数的常用的有四种形式:
(1)Date()
(2)Date(int year, int month, int date):以int型表示年、月、日。
(3)Date(int year, int month, int date, int hrs, int min):以int型表示年、月、日、时、分。
(4)Date(int year, int month, int date, int hrs, int min, int sec):以int型表示年、月、日、时、分、秒。
在长整型和Date类之间有一个对应关系,就是将一个时间表示为距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。对于这种对应关系,Date类也有其相应的构造函数:Date(long date)。
获取Date类中的年、月、日、时、分、秒以及星期读者可以使用Date类的getYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getDay()方法。
而Date类的getTime()方法可以得到前文中所说的一个时间对应的长整型数,与包装类一样。此外,Date类也有一个toString()方法可以将其转换为String类。
【例3-13】日期型数据处理示例
3-13.jsp
<%@ page import="java.util.*" %>
<%@ page contentType="text/html; charset=gb2312" %>
<HTML>
<head><title>日期型数据处理示例</title></head>
<BODY>
你好,今天是
<%
Date today=new Date();
%>
<%=today.getDate()%>号,
星期<%=today.getDay()%>
<h1>现在是北京时间: <%=today.toString() %>
</h1>
</BODY>
</HTML>
上述程序代码创建一个Date类的对象,用getDate()方法获取对象的时间,并getDay()求当天的日期。其程序运行结果如图3-20所示。
图3-20 日期型数据处理示例运行结果
“<%@”和“%>”之间为JSP指令,常用下列三种指令:
<%@ page import="java.util.*" language="java" session="true" %>
<%@include file="包含文件的URL"%>
<%@taglib uri="URIToTagLibrary" prefix="tagPrefix"%>
其中:JSP指令的关键词page、include、taglib赋予指令不同类型的语义。每个JSP指令的关键词后面是“KEY=VALUE”形式的值对,其中KEY是属性名,VALUE是字符串类型的属性值。这里我们介绍最为常用的page和nclude指令,taglib指令在后面的章节还会进行讲解。
page指令用于定义JSP页面中的全局属性。<%@page%>指令作用于整个JSP页面,包括被静态包含的文件,但是<%@page%>指令不能作用于被动态包含的文件。page指令语法格式如下:
<%page [language="java"] [extends="package.class"]
[import="{package.class │package.*}, … …"] [session="true │false"]
[buffer="none│8kb│sizekb"] [isThreadSafe="true │false"]
[info="text"] [errorPage="relativeURL"]
[contentType="mimeType[;charset=characterSet]"│"text/html;charset=ISO-8859-1"]
[isErrouPage="true│false"]
%>
在一个页面中可以使用多个<%@page%>指令,除import属性以外的其它属性只能设置一次。页面中的import属性和Java中的import语句类似,可以多次设置。JSP页面指令是一种功能比较复杂的指令,这主要与它所要支持的繁多的属性有关。下面对page指令中可以包含的各个属性进行详细说明。
(1)language
language属性告诉服务器在文件中将采用哪种编程语言作为脚本语言,默认为Java。
(2)extends
extends 属性定义了由JSP 页面产生的servlet 的父类。一般来说,这个属性不会用到,只有需要实现一些特殊功能时才会用到。
(3)import
import属性用来声明输入引用的Java包(package)或(class) 。这是唯一可以在同一个JSP页面中重复出现的属性设置。
import属性的值是一系列用逗号分开的列表,指明想要引入的包和类。例如:
<%@ page import="java.util.*" %>
可以在程序中引入多个需要的包和类,包和类之间用逗号分隔。例如:
<%@ page import="java.util.*,java.io.*" %>
也可以将需要引入的多个包和类写在多个page指令中。例如,上面的语句等价于:
<%@ page import="java.util.*" %>
<%@ page import=" java.io.*" %>
当使用import引入了包和类后,就可以使用与这些包和类相关的方法和对象了。
【专家提示】java.lang.*、javax.servlet.*、javax.servlet.jsp.*和javax.servlet.http.*包已经作为缺省值被JSP引入,所以不需要在网页中再次引入。
(4)session
session 属性表示当前页面是否加入会话期间的管理,其缺省值为true, 表明内建对象session存在(如果没有session对象,则会新建一个),由session对象来管理会话。如果设session属性值为false,则内建对象session不存在,这样页面中任何使用到session 的语句都会产生编译错误。
(5)buffer
buffer决定输出流(out 对象)是否需要缓冲区,缺省值是8KB, 也可以设置为none(没有缓冲区)或所指定大小的缓冲区,例如:
<%@page buffer ="12kb" %>
上面的语句指定输出流缓冲区为12KB。
buffer 属性通常与autoFlush属性配合使用。
(6)autoFlush
autoFlush属性用于指定是否自动刷新输出缓冲,如果设成true,则当输出缓冲区满的时候,自动刷新缓冲区而不是抛出一个异常,缺省值为true。
【专家提示】同时设置autoFlush为false和buffer为none是不合法的,编译时将会出错。
(7)isThreadSafe
isThreadSafe属性指示JSP 引擎,网页在处理对象存取时是否要引入ThreadSafe( 线程保护)机制,缺省值为true,此时如果多个客户向JSP 引擎发送请求,就可以同时被处理。这时JSP 程序员要处理同步时的共享状态,以保证同步确实是安全的。如果isThreadSafe 被设成false,则采用单线程模式控制客户端访问该页面。
(8)info
info属性用于设置页面的说明信息文字,可以通过页面的Servlet.getServletInfo() 方法访问该信息。例如:
<%@page info="JSP 教程" %>
(9)ErrorPage
ErrorPage 属性用于指示一个JSP 文件的相对路径,以便在页面出错时,转到这个JSP 文件来进行处理。相应的,需要将这个JSP 文件的isErrorPage 属性设为true。
当ErrorPage 属性被设置后,JSP 网页中的异常仍然会产生,只不过此时捕捉到的异常将不由当前网页进行处理,而是由 ErrorPage 属性所指定的网页去进行处理。
(10)isErrorPage
isErrorPage 属性指示一个页面是否为错误处理页面。设置为true 时,在这个JSP 页面中的内建对象exception 将被定义,其值将被设定为呼叫此页面的JSP 页面的错误对象,以处理该页面所产生的错误。isErrorPage 属性缺省值为false,此时将不能使用内建对象exception来处理异常,否则将产生编译错误。
(11)contentType
contentType属性用于设置JSP 文件和最终文件的MIME 类型和字符集的类型。这一项必须在文件的顶部。可用的MIME类型有text/plain、text/html、text/html 和image/gif、image/jpeg等。contentType属性缺省值为“text/html;charset = ISO8859_1”,为了让JSP页面可以正常地显示中文需要设置为“text/html;charset = GBK”或“text/html;charset =gb2312”。
include指令指定在JSP文件中包含的一个静态的文件,即在JSP文件被编译时需要插入的文本或代码。include指令语法格式如下:
<%@include file="relativeURL"% >
如果这个路径以“/”开头,那么这个路径主要参照JSP应用的上下文关系路径,如果路径是以文件名或目录名开头,那么这个路径就是正在使用JSP文件的当前路径。
<%@include %>指令将会在JSP编译时输入一个包含文本或代码的文件,当使用 <%@include %> 指令时,包含的过程是静态的。静态的包含就是指这个被包含的文件将会被导入到JSP文件中去,这个被包含的文件可以是JSP文件、HTML 文件、文本文件。如果被包含的是JSP文件,这个被包含JSP的文件的代码将会被执行。
【专家提示】包含文件可以是html文件、jsp文件、文本文件、或者只是一段Java代码,但是注意在这个包含文件中不能使用<html>、</html>、<body>、</body>标志,因为这将会影响在原 JSP文件中同样的标志,这样做有时会导致错误。
在JSP页面中,包含指令最常见的用途就要数网页导航条了,由于一个网站的主导航条栏往往是统一的,所以主导航栏一般被写成一张单独的网页,然后通过框架结构与其他网页拼接。由于框架可能带来的诸多的不便。如用户难以对框架内网页做书签等,包含指令就成了实现导航栏的最佳机制。
【例3-14】include指令应用示例
3-14.jsp
<%@page contentType="text/html;charset=GB2312"%>
<html>
<head>
<title>JSP指令示例</title>
</head>
<body>
<h1>**金字塔**</h1>
<%@ include file="Ta.jsp" %>
</body>
</html>
Ta.jsp源程序如下,功能是输出一个数字构成的金字塔。
<% out.print("<pre>");
int i=7,j,k;
for(j=1;j<i;j++){
for(k=0;k<2*(i-j-1);k++)
out.print(" ");
for(k=0;k<j;k++)
out.print(j+" ");
%>
<P></P>
<%
}
out.print("</pre>");
%>
这里将两个程序放在同一目录下面,3-14.jsp包含Ta.jsp,实现了静态文件的插入。include指令应用示例运行结果如图3-21所示。
图3-21 include指令应用示例
第4章 隐含对象解析