一个Jsp初学者的学习过程(一)
TheUnforgiven
前言
从现在开始我要把我学习Jsp的过程写出来。这些东西都是我从书本、网络上搜集整理的,我把它们据为己有后写这样一篇总结供如我一样的初学者参考。
请容许我在这里说一些和读者无关的话,对此不感兴趣的请直接跳到第一章或第二章。
我在2003年七月大学毕业,这之前学了四年计算机专业,由于基本是属于文科学校的计算机专业,学校女生少男生多学习的风气极受影响,所以可以想象我毕业时候的水平。在学校时学习的大多是枯燥的计算机理论知识,我虽知其有用,但实在不感兴趣,我感兴趣的是编码,于是学了一个学期的pascal,又编了一个学期的C(学C的时候是热情高涨的,甚至教课的老师允许或者说支持我逃课回去编码),遇指针、链表,不成,弃之,转而学C++,不半月,遇“对象”、“类”、“继承”,不成,复弃之,终不成,无奈之下,日夜游戏,不思进取,不数载,毕业。
这以后直至现在一直在一省直机关的信息中心工作,由于是“事业单位”,所以工作很闲,头半年学了两个月的html,后又学一个月的Asp,由于缺少压力,最终都放弃了。直到我们单位开始了一个项目——电子政务,我的境况有了转变。
我们找来了两家公司给我们开发软件,领导说让我跟一跟,学写东西,由于当年C给我的打击实在太大了,我已认定自己不是那块料,是不具有学程序的天赋的,所以有些不情愿,但是终于由于太闲而且又不甘心自己“一点技术含量都没有”,最终选择了学习Jsp。我找给我们开发软件的一个程序员朋友,向他要来了Tomcat、jsdk和盗版的Oracle,编写平台就先暂时用我比较熟悉的Dreamweaver,英文也差,就没用Jbuilder、Jcreator什么的,至于资料,没有,只有网络,我就这样开始了我的Jsp之旅。
我没想到的是当年学的那一点点C、html、Asp让我不怎么费力的就走进(近)了Jsp的大门,这速度至少出乎了我的意料。
值得说明的一点是:我学Jsp完全是从实例入手,这之前我的相关理论知识基本为零,所以我在对代码的理解上(很大程度表现在注释上)是使用自己的“土语”的,而不是“术语”。我的原则是这篇文字能够让和我一样的初学者能够看懂。
对于一个毫无基础的人来说,你对他说“类”、“对象”、“接口”、“继承”这些名词,他是无法理解的,因为它们太抽象,所以我必须通过实例和不怎么规范的语言使它们具体化一些。
由于我的水平实在有限,可能会出现很多错误,尤其在对某些“代码”的理解上,但是我勇于拿出板砖,希望有热心的高手使劲扔玉^_^这是我的邮箱:windowsmx@sohu.com。
最后,感谢互联网及在其上分享自己经验的程序员、我的单位的领导、同事、程序员朋友孙罡、大学的朋友彭涛等。
第一章 配置服务器环境
Jsp全称是Java Server Pages(而不是JavaScript的缩写,JavaScript是使用Java语言的一种脚本语言),用我的话说,它就是一堆使用于网页浏览器上的代码(或者说代码规范),从这个角度讲和Asp类似。它并不是一种编程语言,但是它需要一种编程语言来编写其中的程序,正如Asp使用VB作为编程语言一样,Jsp使用的是Java语言。
安装软件:
既然Jsp使用Java,那么我们的服务器操作系统里当然要有相应的Java环境,否则我们怎么使用Java提供的“库函数”呢?JDK就是这个东西,我们可以从SUN公司的网站上下载它,先把它安装到操作系统(我的操作系统是Windows XP Professional SP2)中,我的安装目录是:D:\j2sdk1.4.2_07,装完之后我们还需要进行配置,这一步在下面再说。
我们还需要安装Web服务器,我们初学者一般可以选用Tomcat作为Jsp的Web服务器。Web服务器是什么东西?假如你对Asp有一点了解的话,你就会知道IIS这东西——IIS就是Asp的Web服务器,那么Tomcat对于Jsp来说,它就相当于Asp的IIS。我使用的是Tomcat5.0,你也可以使用更高的版本,注意在安装它之前你得先安装JDK,我的Tomcat的安装目录是:D:\Tomcat 5.0。
配置:
右键“我的电脑”-“属性”-“高级”-“环境变量”,这里面有用户变量和系统变量之分,说实话,用户变量主要起什么作用我不是很清楚,但是系统变量一定是很重要的,通过“新建”或“编辑之后”,我的相关的用户变量是这样的:
classpath——.;d:\j2sdk1.4.2_07\lib\tools.jar;d:\j2sdk1.4.2_07\lib\dt.jar;
java_home——d:\j2sdk1.4.2_07
path——d:\j2sdk1.4.2_07\bin;d:\j2sdk1.4.2_07
我的相关的系统变量是:
CATALINA_HOME——d:\Tomcat 5.0
classpath——.;d:\j2sdk1.4.2_07\lib\tools.jar;d:\j2sdk1.4.2_07\lib\dt.jar;
JAVA_HOME——d:\j2sdk1.4.2_07
Path——d:\j2sdk1.4.2_07\bin;d:\j2sdk1.4.2_07;(把这句添加进去,而不是最终的值)
TOMCAT_HOME——d:\Tomcat 5.0
Tomcat在安装完之后在Windows系统的“服务”中会多一项“Apache Tomcat”的服务,它是自动的,你可以给它改成手动,这样在不使用的时候可以节省一些系统资源了。既然改成手动了,那么怎么启动它呢?找这两个文件:D:\Tomcat 5.0\bin\startup.bat和D:\Tomcat 5.0\bin\shutdown.bat,前一个就是启动Tomcat的批处理文件了,而后一个就是关闭的。
你在安装Tomcat的时候可能会发现安装过程中有一个地方可以改端口号,默认是“8080”,而当你在调试程序时你就要注意这个端口号了。在上面的配置都完成以后,你可以看看是否成功了:先开启Tomcat服务器,然后在网页地址栏里输入:http://localhost:8080/(客户端和服务器是同一台机器),安装成功的话你会看见Tomcat的欢迎界面。你也可以使用你的IP或是机器名,比如我的IP是172.16.20.30,机器名是ringz,那么输入以下两种形式都是可行的:http://172.16.20.30:8080/,http://ringz:8080/。
一个Jsp初学者的学习过程(三)
TheUnforgiven
第三章 连接数据库
在最初几天我写了几个页面之后,我决定要做一个留言板之类的东西:有登录验证、注册、发表文章、浏览文章、管理文章、管理用户等这些功能。首先的登录验证这个不难,但是有个问题:需要连接数据库了。于是我开始查找资料,并安装了Oracle数据库(对于Oracle数据库的一些最基本的知识我就不在这里说明了,但是需要注意的两点是:一、安装完成后就不要再改变你的机器名,一旦改了再改回来,数据库也用不了;二、安装完后不要使用Windows优化大师的清理注册表垃圾的功能,它会删掉一个有用的注册表信息导致Oracle的监听无法启动),最后写了这个文件:
-----------------------------link.jsp-----------------------------------------
<%@ include file="include.inc"%>
<%@ page contentType="text/html;charset=gb2312"%>
<html>
<body>
<%
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try
//有try就至少要有一个catch或finally
{
Class.forName(CLASSFORNAME);//载入驱动程式类别
con=DriverManager.getConnection(SERVANDDB);//建立数据库连接
stmt=con.createStatement();
String sql="select * from infom";//infom是表名
rs=stmt.executeQuery(sql);
while(rs.next())
{
out.println(rs.getString(1));//1就是第一个字段,第一个字段的名是username,所以这段也可以写成:rs.getString("username")
out.println(rs.getString(2));
}
out.println("<br>成功!");
}//try结束
catch(Exception e)
//当try里运行出错时,运行catch里的内容
{
out.println(e);//输出错误信息
}
finally
//不论是否出错、结果怎样,都要运行finally里的内容
//向下为关闭数据库连接
{
if (rs!=null)
rs.close();
if (stmt!=null)
stmt.close();
if (con!=null)
con.close();
}
%>
</body>
</html>
---------------------------------------------
Class.forName(CLASSFORNAME);
con=DriverManager.getConnection(SERVANDDB);
这两句无疑是很重要的,可是CLASSFORNAME、SERVANDDB这两个变量是什么呢?它们都来自<%@ include file="include.inc"%>这句里的include.inc文件,该文件与link.jsp在同一目录下。
-----------------------------------include.inc------------------------------------
<%@ page import="java.sql.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<%@ page import="oracle.jdbc.driver.OracleDriver"%>
<%@ page import="java.lang.*"%>
<%
request.setCharacterEncoding("gb2312");
String CLASSFORNAME="oracle.jdbc.driver.OracleDriver";//定义载入驱动程式的字符串
String SERVANDDB="jdbc:oracle:thin:name/password@ringz:1521:rock";//定义建立数据库连接的字符串
//name是数据库的用户名;password是该用户的密码;ringz是我的机器名;rock是SID
%>
----------------------------------------------
假如你用的是Oracle的数据库的话,现在你运行这个文件还是会出错,因为Tomcat服务器找不到Oracle的JDBC驱动,你需要甲骨文(oracle)公司提拱的一个包:classes12.jar,你可以在D:\oracle\ora92\jdbc\lib下找到它,然后把它放到D:\Tomcat 5.0\common\lib下,现在,应该可以了。
本章最后的话:向程序员方向发展有两点无疑是很重要的:1、试着读懂代码;2、亲自动手写,然后亲自调试。
一个Jsp初学者的学习过程(四)
TheUnforgiven
第四章 第一个Javabean
一、先看看如何取当前时间并显示的代码:
------------------------------------------------
<%
java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date currentTime = new java.util.Date();//得到当前系统时间
String str_date1 = formatter.format(currentTime); //将日期时间格式化
String str_date2 = currentTime.toString(); //将Date型日期时间转换成字符串形式
%>
格式化成"yyyy-MM-dd HH:mm:ss"格式的日期时间:<%=str_date1%>
未经格式化的String格式的日期时间:<%=str_date2%>
未经格式化的Date格式的日期时间:<%=currentTime%>
-------------------------------------------------
页面的输出内容:
格式化成"yyyy-MM-dd HH:mm:ss"格式的日期时间:2005-03-17 09:55:40
未经格式化的String格式的日期时间:Thu Mar 17 09:55:40 CST 2005
未经格式化的Date格式的日期时间:Thu Mar 17 09:55:40 CST 2005
通常我们需要的是这种格式化后的时间:2005-03-17 09:55:40。现在有这样一个问题:“2005-03-17 09:55:40”是一个字符串,有些时候我们需要在这个字符串里提取出年、月、日等的相关信息,怎么办呢?看下面的代码:
----------------------规则的字符串----------------------------------------------
规则的字符串(年4位,月2位,日2位,中间用字符“-”分隔):
<br>原字符串为:
<%
String date="1989-12-30";
out.println(date+"<br>");
String year=date.substring(0,4);//取第0+1位至第4位
String month=date.substring(5,7);//取第5+1位至第7位
String day=date.substring(8,10);//取第8+1位至第10位
out.println("year="+year+",month="+month+",day="+day);
%>
----------------------------------------------------------------------------------
从上面的代码我们可以看出来:这只能针对规则的字符串(年4位,月2位,日2位),要是不规则的呢?年可能2位也可能4位,月和日可能1位也可能2位,怎么办?通过对上面的代码修改,可以得到下面的通用的代码(这个“通用”有一个前提——年月日之间必须以“-”分隔):
----------------------不规则的字符串----------------------------------------------
不规则的字符串(年、月、日长度不一定,中间用字符“-”分隔):
<br>原字符串为:
<%
String date="04-05-6";
out.println(date+"<br>");
int a=date.indexOf("-");//求第一个“-”的位数
int b=date.lastIndexOf("-");//求最后一个“-”的位数
int len=date.length();//求字符串的长度
year=date.substring(0,a);//取第一个“-”前的字符串
month=date.substring(a+1,b);//取两个“-”之间的字符串
day=date.substring(b+1,len);//取最后一个“-”以后的字符串
out.println("year="+year+",month="+month+",day="+day);
%>
----------------------------------------------------------------------------------
现在这个问题解决了。可是我们会想到:每次需要对一个表示年月日的字符串进行分割的时候都需要在.jsp页面里写上这么一段代码,不但麻烦而且使页面显得混乱,能不能以一种看起来更清晰的方法解决这个问题呢?当然可以了,用javabean就行了。
二、第一个javabean
什么是javabean?我在接触到这个问题时苦恼不已,因为我始终无法理解这个概念,直到我相继写了几个之后,我蓦然发现:它不就是一个类吗?!现在,我们先不去管什么是类,先看下面的这个javabean:
--------------------------------DateBean.java-------------------------------------
//该bean能够从jsp文件中得到一个表示年月日(用“-”分隔)的字符串,然后返回给jsp文件分别表示年、月、日的字符串
package ringz.javabeans; //ringz.javabeans是我的包名,我自己写的javabean都在这个包里
public class DateBean //这个class的名字是DateBean,那么这个javabean文件的名就必须叫:DateBean.java
{
private String dateStr;
private String year;
private String month;
private String day;
//
public void setDateStr(String str) //私有变量dateStr的set方法
{
this.dateStr=str;
}
public String getDateStr() //私有变量dateStr的get方法
{
return dateStr;
}
public String getYear()//得到年的字符串
{
int a=dateStr.indexOf("-");//求第一个“-”的位数
year=dateStr.substring(0,a);//取第一个“-”前的字符串
return year;
}
public String getMonth()//得到月的字符串
{
int a=dateStr.indexOf("-");//求第一个“-”的位数
int b=dateStr.lastIndexOf("-");//求最后一个“-”的位数
month=dateStr.substring(a+1,b);//取两个“-”之间的字符串
return month;
}
public String getDay()//得到日的字符串
{
int b=dateStr.lastIndexOf("-");//求最后一个“-”的位数
int len=dateStr.length();//求字符串的长度
day=dateStr.substring(b+1,len);//取最后一个“-”以后的字符串
return day;
}
}
---------------------------------------------------------------------------------
一个javabean里最主要的是set和get方法:set方法用于从.jsp页面向javabean传值;get方法用于从javabean向.jsp页面传值。下面看.jsp页面如何使用这个javabean:
------------------------------ymd_use_bean.jsp----------------------------------
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
<jsp:useBean id="ymd" scope="page" class="ringz.javabeans.DateBean">
<jsp:setProperty name="ymd" property="*"/>
</jsp:useBean>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>使用javabean从字符串中取得年月日信息</title>
</head>
<body>
<%
try
{
out.println("您输入的字符串是:"+ymd.getDateStr()+"<br>");
out.println("year="+ymd.getYear()+",month="+ymd.getMonth()+",day="+ymd.getDay());
}
catch(Exception e){}
%>
<br><br><hr><br>请在下边的文本框中输入代表年月日的字符串,格式:XXXX-XX-XX,其中代表年、月、日的位数可以不限定。
<form method="post" action="ymd_use_bean.jsp">
<input type="text" name="dateStr"><!--必须和所使用的javabean:DateBean中的这个“private String dateStr;”所定义的名称完全一致!!!-->
<input type="submit" value="确定">
(必须使用两个“-”分开,如:1999-9-29)
</form>
</body>
</html>
--------------------------------------------------------------------------------
你在这段代码里能看到get方法,可是set方法呢?怎么没看见?这里面的玄机在<jsp:useBean></jsp:useBean>之间和form里的这句:<input type="text" name="dateStr">,这里我不想重点说明.jsp文件如何引用javabean,你不清楚的话请查阅其他资料。
另外在这里提一个小技巧你自己试一试:把try和catch的内容去掉,看看结果是什么样的;把catch的内容改成这样:
catch(Exception e)
{out.print(e);}
再看看结果是什么样的。然后自己分析一下为什么会这样。这是一个我经常使用的小技巧,不知道别人是不是也用这种方法来解决这种问题。
上面已经说了javabean就是一个类,下面我要用自己的话说一下什么是类,我是怎么理解类这个概念(理解的不一定准确,还请高手们给予指正,免的误人子弟^_^!):
先是想起一个笑话:说有一种机器,从机器的一侧放进一头猪,机器的另一侧就会出香肠。引申一下。这台机器在一个仓库里,这个仓库里还有一台能自动出猪毛和一台出猪皮的机器。现在这个仓库就可比做一个类,而每台机器就是一个方法,因为这个仓库是只针对猪的仓库,所以这个仓库一定在java.pig这个包(java的API——说白了就是类库或者按照C的说法就是函数库——里有很多类,这些类是分类存放的,每一个分类称做一个包,比如,和输入输出有关的类就放在java.io包里,和绘制图形相关的类就放在java.awt包里)里面,我们给这个仓库起名叫PigFactory,这就是类名。现在拿来一头猪:Japanese属于类Pig,先通过和PigFactory同名的构造函数PigFactory()为处理这头猪新建一个实例:
java.pig.PigFactory pf = new java.pig.PigFactory();
现在我们可以通过这个实例对这头猪进行操作了——由于我们只想要它的皮,那就使用出皮的机器就行了,这台机器作为一个方法叫做getSkin(),那么:
Skin pigskin = pf.getSkin(Japanese);
猪皮(pigskin)出来了,并且运送出仓库,它属于类“皮”(Skin)了。
类似的,还有一些专门处置牛、羊的仓库,它们也有自动出皮的机器,所以也是方法:getSkin(),这也就是为什么我们会发现很多不同的类里边有相同名称的方法,如:getString方法。
我们可以发现:这台自动出皮的机器是如何工作的,我们并不关心,我们所关心的只是怎样使用它。我们也可以自己开发一个类(或者javabean),它的工作原理和SUN给我们开发好的API里的类是基本一致的。在使用时我们所关心的仅仅是如何把值传给它和如何从它那里得到值。
以上是我的理解,可能有很多不确切的地方,希望大家指正。
说了这很多废话以后,你可能想问:我们上面写的javabean现在可以用了吗?还不行。刚刚我们写好的是一个.java文件,必须把它编译成.class文件以后Jsp才能调用它。下面说怎么编译,由于我现在没有使用专门的java开发工具(如JBuilder),所以只能使用我们安装的JDK(java 2 sdk)所提供的编译工具:
把DateBean.java这个文件放到C:\下,“开始”-“运行”-“cmd命令”,在开启的窗口中将当前路径改为C:\,然后输入:javac DateBean.java,回车,如果窗口中没有提示出错的话,OK,编译成功了。这时你会发现和DateBean.java处于同目录的地方多了一个DateBean.class文件,就是它了。现在的问题是它应该放在哪了。由于是我自己写的javabean,所以我不打算把他们和Tomcat自带的放在一起:之前我们定义了自己的根目录:e:\MyJsp,在它的下面新建一个WEB-INF文件夹(注意大小写),其下再建一个classes文件夹,放在这里就行了。当然你可以专门为你自己开发的javabean做一个包——就像SUN那样——我自己的包名叫ringz.javabeans,所以我在classes文件夹下建了一个ringz的文件夹,里面再建一个javabeans文件夹,然后把我开发的.class文件放到这里。这时使用的时候要注意包名:<jsp:useBean id="ymd" scope="page" class="ringz.javabeans.DateBean" />。
本章需要注意的当然是每次改完后的.java文件都要重新编译成.class文件,而且使用.class文件时要重启Tomcat服务器。
一个Jsp初学者的学习过程(五)
TheUnforgiven
第五章 分页功能的实现
在我逐步把我的留言板的功能完善的同时,我渐渐熟悉了对数据库的操作,这时我发现留言信息的目录越来越长了,我需要实现一个分页功能了,最初我尝试自己解决这个问题:
1、我应该把它的关键部分封装成一个bean,使它尽可能的能够重用;
2、通过资料了解有两种数据库查询方案:一、一次取得所有资料,然后在指定的页显示指定的资料;二、分次查询数据库,每次只获得本页的数据。考虑到数据库中记录数越多,方案一所占的服务器资源就越多(将所有的记录都放到内存中,假如有50万条记录的话……@$^*%@#),所以应该采用方案二;
3、首先要知道目标数据库里共有多少条记录(select count(*) from 表名),然后确定每页显示多少条记录,再根据它计算一共分多少页(最大页数)显示,这部分由bean1(在我的代码里就随便起个名叫PageBean)实现;获取当前要显示第几页的请求,查询本页要显示哪些条记录,将每条记录的内容作为一组数据返回给显示页面,这部分由bean2(CountBean)实现;显示页面(.jsp文件)显示各条记录的内容。
到这里我发现有两个难点:(1)查询从第m条到第n条记录的SQL语句不会写,通过在网上查找资料,这个问题得到解决;(2)bean2返回给显示页面的值是个二维的数组,这个数组怎么传呢?于是不得不上网翻书查找资料,最终发现由Vector(向量)来解决,由于没有工具书,无法针对Vector进一步学习,就只好分析代码,好在最后分析明白了——到目前为止,也只是明白了那段代码,仍然无法做到能够应用。
下面是这三个文件的代码:
-----------------------------------------PageBean.java-----------------------------------------------
//该bean用于实现分页功能时得到总的记录数和最大的页数
package ringz.javabeans;
import java.io.*;
import java.sql.*;
public class PageBean
{
private int maxRowCount;//最大记录数
private int onePageRowCount;//每页显示的记录数
private int maxPageCount;//最大页数
private String classforname;
private String servanddb;
private String sql;
//
//得到关于目标数据库的搜索条件
public void setSql(String s1,String s2,String sql)
{
this.classforname=s1;
this.servanddb=s2;
this.sql=sql;
}
//得到onePageRowCount
public void setOnePageRowCount(int counts)
{
onePageRowCount=counts;
}
//计算maxRowCount并返回
public int getMaxRowCount()throws Exception
{
try
{
Class.forName(classforname);//载入驱动程式类别
Connection con=DriverManager.getConnection(servanddb);//建立数据库连接
Statement stmt=con.createStatement();//建立Statement变量
ResultSet rs=stmt.executeQuery(sql);
if (rs.next())
maxRowCount=rs.getInt(1);
rs.close();
stmt.close();
con.close();
return maxRowCount;
}//try
catch (Exception e)
{
e.printStackTrace();
throw e;
}
}//getMaxRowCount()
//根据maxRowCount和onePageRowCount计算出maxPageCount并返回
public int getMaxPageCount()
{
if (maxRowCount%onePageRowCount==0)
maxPageCount=maxRowCount/onePageRowCount;
else
maxPageCount=maxRowCount/onePageRowCount+1;
return maxPageCount;
}
}
---------------------------------------------------------------------------------
----------------------------CountBean.java------------------------------------
//该bean用于接收具体页数然后返回该页应显示的记录
package ringz.javabeans;
import java.util.*;
import java.io.*;
import java.sql.*;
public class CountBean
{
private int pageNum;//当前是第几页
private String classforname;
private String servanddb;
private String sql;
Vector v=new Vector();
//得到关于目标数据库的搜索条件
public void setSql(String s1,String s2,String sqlstr)
{
this.classforname=s1;
this.servanddb=s2;
this.sql=sqlstr;
}
//得到pageNum
public void setPageNum(int pagenum)
{
this.pageNum=pagenum;
}
//返回结果
public Vector getResult(String listname[])throws Exception
{
int num=listname.length;//得到数组的长度
String listName[]=new String[num];//定义一个大小为num的string型数组
for(int i=0;i<num;i++)
listName[i]=listname[i];//将目标数组的内容传给listName数组
try
{
Class.forName(classforname);
Connection con=DriverManager.getConnection(servanddb);
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery(sql);
int i=1;
while(rs.next())
{
Object[] obj=new Object[num];
for(int j=0;j<num;j++)
obj[j]=rs.getString(listName[j]);
v.add(obj);
i++;
}//while
rs.close();
stmt.close();
con.close();
return v;
}//try
catch(Exception e)
{
e.printStackTrace();
throw e;
}//catch
}
}
----------------------------------------------------------------------------------
编译上面这两个文件的时候,发现如果不把“错误”扔掉(throw e),就无法编译成功,我不明白具体原因。
-----------------------------------page.jsp---------------------------------------
<%@ include file="include.inc"%>
<%@ page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="page1" scope="page" class="ringz.javabeans.PageBean"/>
<jsp:useBean id="page2" scope="page" class="ringz.javabeans.CountBean"/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>分页的实现</title>
<style type="text/css">
<!--
body {
margin-left: 10%;
margin-right: 10%;
}
-->
</style>
<script language="JavaScript" type="text/JavaScript">
<!--
function jumping(jump){ //v3.0 ***用于页面跳转
var pageID=jump.value;
var url=pageID;
window.location.href = url;
}
//-->
</script>
</head>
<body>
<%
int pageNum;
try
{
pageNum=Integer.parseInt(request.getParameter("page"));//得到“要显示第几页”
}
catch(Exception e)
{
pageNum=1;//如果出错说明pageNum没有接收到"page",那么就把pageNum初始为1
}
int onePageRowCount=10;//每页的条数************按需要改变
String s1="oracle.jdbc.driver.OracleDriver";//定义载入驱动程式的字符串
String s2="jdbc:oracle:thin:name/password@ringz:1521:rock";//定义建立数据库连接的字符串************按需要改变
String sql="select count(*) from article";//确定记录总数的查询语句************按需要改变
page1.setSql(s1,s2,sql);
page1.setOnePageRowCount(onePageRowCount);
int maxRowCount=page1.getMaxRowCount();//获得记录总数
int maxPageCount=page1.getMaxPageCount();//获得总的页数
page2.setPageNum(pageNum);
String listname[]={"ID","author","time","title"};//要查询的字段名************按需要改变
int max=pageNum*onePageRowCount;//本页最后一条记录的行号
int min=(pageNum-1)*onePageRowCount+1;//本页第一条记录的行号
String sqlstr="select b.* from (select a.*,rownum row_num from (select * from article order by time desc) a where rownum<=''"+max+"'') b where row_num>=''"+min+"''";//************按需要改变
page2.setSql(s1,s2,sqlstr);
if(maxRowCount>0)
out.println("<div align=''left''>共有"+maxRowCount+"条记录,每页显示"+onePageRowCount+"条。</div>");
%>
<table width="100%" border="1" align="center" cellpadding="0" cellspacing="0" bordercolorlight="#000000">
<tr bgcolor="#00CCFF">
<td align="center">标题</td>
<td align="center">作者</td>
<td align="center">日期</td>
</tr>
<%
java.util.Vector v=page2.getResult(listname);
java.util.Enumeration e=v.elements();
while(e.hasMoreElements())
{
Object[] obj=(Object[])e.nextElement();//****************注意修改下面的几行
String id=obj[0].toString();
String name=obj[1].toString();
String time=obj[2].toString();
String title=obj[3].toString();
out.println("<tr>");
out.println("<td bgcolor=''#eeeeee''><div align=''left''><font color=''#eeeeee''><a href=view.jsp?ID="+id+">"+title+"</a></font></div></td>");
out.println("<td width=''15%'' bgcolor=''#ffff99''><div align=''center''>"+name+"</div></td>");
out.println("<td width=''30%'' bgcolor=''#9999ff''><div align=''center''>"+time+"</div></td>");
out.println("</tr>");
}
%>
</table>
<div align="right">
<%
String fileName="page";//**************************将文件名作为变量***********************
out.print("第<font color=red>"+pageNum+"</font>页 共"+maxPageCount+"页 ");
if (maxPageCount>1)//不只有一页
{
if (pageNum==1)//当前页是首页
{
out.print("首页 | 上一页 | <a href="+fileName+".jsp?page="+(pageNum+1)+">下一页</a> | ");
out.print("<a href="+fileName+".jsp?page="+maxPageCount+">尾页</a> ");
}//if (pageNum==1)
else
{
if (pageNum==maxPageCount)//当前页是尾页
{
out.print("<a href="+fileName+".jsp?page=1>首页</a> | ");
out.print("<a href="+fileName+".jsp?page="+(pageNum-1)+">上一页</a> | 下一页 | 尾页 ");
}//if (pageNum==maxPageCount)
else//当前页不是上面的2种情况
{
out.print("<a href="+fileName+".jsp?page=1>首页</a> | ");
out.print("<a href="+fileName+".jsp?page="+(pageNum-1)+">上一页</a> | ");
out.print("<a href="+fileName+".jsp?page="+(pageNum+1)+">下一页</a> | ");
out.print("<a href="+fileName+".jsp?page="+maxPageCount+">尾页</a> ");
}
}
%>
跳转到第
<select name="jumps" onChange="jumping(this)">
<%
for (int i=1;i<=maxPageCount;i++)
{
if (i==pageNum)
{%>
<option value="<%=fileName%>.jsp?page=<%=i%>" selected><%=i%></option>
<%} else {%>
<option value="<%=fileName%>.jsp?page=<%=i%>"><%=i%></option>
<%} } %>
</select>
页
<%
}//if (maxPageCount!=1)
%>
</div>
</body>
</html>
----------------------------------------------------------------------------------
整个的分页功能写完后,我发现还是有很大的不足:显示分页的页面(page.jsp)代码太多,其他页面引用该功能的时候还是要从这里复制大段的代码,而且其中需要根据实际情况改动的地方多达七处(标注很多*的地方),这很容易出错,不利于管理使用,但是至今我仍找不到一个合适的方法解决这个问题——希望高手们扔玉。