Jsp页面分页技术实现文档
<1>分页的设计思路:
1.1:在jsp中直接分页
这种分页方法将分页代码统一编写在jsp中,开发比较简单,但是在页面比较多的时候维护起来比较麻烦复杂。
1.2:在Servlet中实现分页
这种方法采用JSP+Servlet进行开发,页面显示代码与控制代码分离。
1.3:在JavaBean中实现分页
这种方法采用JSP+JavaBean进行开发,页面显示代码与业务逻辑代码相分离。
1.4:万能分页技术
一般分页时需要考虑具体的数据表的读写以及显示,采用万能分页技术,则可以对任意的表(或者任意查询SQL)进行分页。
1.5:结合不同是数据库实现方式,上述4中方法都是基于ResultSet里的数据来进行分页,存在性能和资源占用等问题,结合不同数据库的特点和功能,设计出性能优良好占用资源较少的分页程序。
第一种分页
1.1:在jsp中直接分页(代码)
Page.jsp
<%@ page contentType="text/html;charset=UTF-8"%>
<%
java.sql.Connection sqlCon; //数据库连接对象
java.sql.Statement sqlStmt; //SQL语句对象
java.sql.ResultSet sqlRst; //结果集对象
java.lang.String strCon; //数据库连接字符串
java.lang.String strSQL; //SQL语句
int intPageSize; //一页显示的记录数
int intRowCount; //记录总数
int intPageCount; //总页数
int intPage; //待显示页码
java.lang.String strPage;
int i;
//设置一页显示的记录数
intPageSize = 10;
//取得待显示页码
strPage = request.getParameter("page");
if(strPage==null){
//表明在QueryString中没有page这一个参数,此时显示第一页数据
intPage = 1;
} else {
//将字符串转换成整型
intPage =java.lang.Integer.parseInt(strPage);
if(intPage<1) intPage = 1;
}
//装载JDBC驱动程序
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String username = "sa"; //用户名
String password = "ambow"; //密码
String url="jdbc:sqlserver://localhost:1433;databaseName=ambow";
//连接数据库
sqlCon=java.sql.DriverManager.getConnection(url,username,password);
//创建语句对象
sqlStmt =sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);
//创建查询语句
strSQL = "select * from userinfo";
//执行SQL语句并获取结果集
sqlRst = sqlStmt.executeQuery(strSQL);
//获取记录总数
sqlRst.last();
intRowCount = sqlRst.getRow();
//记算总页数
intPageCount = (intRowCount+intPageSize-1) /intPageSize;
//调整待显示的页码
if(intPage>intPageCount) intPage = intPageCount;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>数据分页显示title>
head>
<body>
<center><table border=1 cellspacing=0 cellpadding=0>
<tr>
<td align=center width=100% colspan=5 bgcolor=#3399ff>
<font color=#ffffff>成员列表font>
td>
tr>
<tr>
<th>登录名称th>
<th>登录密码th>
<th>电子邮件th>
tr>
<% if(intPageCount>0) {
//将记录指针定位到待显示页的第一条记录上
sqlRst.absolute((intPage-1)* intPageSize + 1);
//显示数据
i = 0;
while(i %> <tr> <td> <%= sqlRst.getString(2) %> td> <td> <%= sqlRst.getString(3) %> td> <td> <%= sqlRst.getString(4) %> td> tr> <% sqlRst.next(); i++; } } %> table>center><br> <center> 第<%=intPage%>页 共<%=intPageCount%>页 <% //以下是分页的“上一页”“下一页”,有上一页就有链接,没有就为文字,下一页同理%> <% if(intPage>1){ %> <a href="page.jsp?page=<%=intPage-1%>">上一页a> <% }else{ %> 上一页 <%}%> <% if(intPage <a href="page.jsp?page=<%=intPage+1%>">下一页a> <% }else{ %> 下一页 <%}%> <center> body> html> <% //关闭结果集 sqlRst.close(); //关闭SQL语句对象 sqlStmt.close(); //关闭数据库 sqlCon.close(); %> 结论: 1.优点:直观,易于理解,并且比较灵活 2.缺点:这种方式只适合对单一的或极少量的结果集进行分析,实现代码不能够被重用,不适合用于实现数据量大、数据表多的结果集的分页显示。 第二种分页技术 1.2:在Servlet中实现分页 1.JSP当中调用 <%@ page contentType="text/html;charset=UTF-8" %> <%@ page pageEncoding="UTF-8"%> <%@ page language="java" %> <%@ page import="java.util.Collection,java.util.Iterator"%> <%@ page import="com.ambow.xmk.page.DBConn.DB_Conn"%> <%@ page import="com.ambow.xmk.page.Entity.DB_User"%> <%@ page import="com.ambow.xmk.page.Entity.User"%> <table align=center border=0 width=100% cellspacing=1 cellpadding=1> <tr> <td width=100% colspan=5 bgcolor=#3399ff> <center><font color=#ffffff>成员列表font>center> td> tr> <tr> <td width=10% bgcolor=#fcfcfc>用户名td> <td width=10% bgcolor=#fcfcfc>登录密码td> <td width=15% bgcolor=#fcfcfc>邮件地址td> tr> <% if (request.getAttribute("c") == null) { %> <tr> <td width= 75% colspan=5 bgcolor=#fcfcfc align=center>没有用户数据!td> tr> <% } else { Collection c = (Collection) request.getAttribute("c"); if (c == null) { %> <tr> <td width=100% colspan=5 bgcolor=#fcfcfc align=center>没有用户数据!td> tr> <% } else { int totalPageNum =((Integer) (request.getAttribute("totalPageNum"))).intValue(); int currentPage = 1; if(request.getParameter("page") != null) { currentPage =Integer.parseInt(request.getParameter("page")); } //输出用户数据 Iterator iterator =c.iterator(); while(iterator.hasNext()) { User user = (User) iterator.next(); %> <tr> <td width=10% bgcolor=#fcfcfc><%=user.getUsername()%>a>td> <td width=15% bgcolor=#fcfcfc><%=user.getPassword()%>td> <td width=15% bgcolor=#fcfcfc><%=user.getEmail()%>td> tr> <%}%> <form name="list" action="./UserListServlet" method="post"> <tr> <td width=100% colspan=5 align=right bgcolor=#efefef> <%for (int i = 1; i <= totalPageNum; i++) {%> <a href="UserListServlet?page=<%=i %>">[<%=i%>]a> <% } %>共[<%=request.getAttribute("totalPageNum") %>]页 <input type="text" size="2"name="page" value=""> <input type="submit" name="go"value="Go"> td> tr> form> <%} } %> <tr> <td colspan=2 align=right> td> tr> table> 2.JAVA类:从数据库中调用数据,根据不同的DB来选定不同的分页函数来分页 public class DB_User { DB_Conn db_conn=new DB_Conn(); //获得用户数量 public int getCount() { db_conn.ConnectDB(); ResultSet rs = null; try { String sql = "selectcount(id) from userinfo"; rs = db_conn.sm.executeQuery(sql); // 执行sql语句 if (rs.next()) { return rs.getInt(1); } return 0; } catch (SQLException SqlE) { SqlE.printStackTrace(); return 0; } catch (Exception E) { E.printStackTrace(); return 0; } finally { // 关闭连接,释放数据库资源: db_conn.CloseDB(); } } // public Collection getAll(int pagesize, int page) { db_conn.ConnectDB(); ResultSet rs = null; try { // sql语句: int startCursor=(page - 1) * pagesize+1; int endCursor=(page - 1) * pagesize+pagesize; System.out.println("start:"+startCursor); System.out.println("end:"+endCursor); String sql = "SELECT* FROM (select *,ROW_NUMBER() Over(order by id) as rowNum from (select * fromuserinfo) as resultTable) as unionTable where rowNum between "+startCursor+" and"+endCursor; // 执行sql语句,返回一个记录集到rs: rs=db_conn.sm.executeQuery(sql); Collection c = new ArrayList(); User user = null; while (rs.next()) { user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("UserName")); user.setPassword(rs.getString("password")); user.setEmail(rs.getString("Email")); user.setRealname(rs.getString("RealName")); user.setGender(rs.getInt("Gender")); user.setQuestion(rs.getString("Question")); user.setAnswer(rs.getString("Answer")); user.setPhone(rs.getString("Phone")); user.setPage(rs.getString("page")); user.setHobbies(rs.getString("Hobbies")); user.setSelfintro(rs.getString("Selfintro")); c.add(user); user = null; } return c; } catch (SQLException SqlE) { SqlE.printStackTrace(); return null; } catch (Exception E) { E.printStackTrace(); return null; } finally { // 关闭连接,释放数据库资源: db_conn.CloseDB(); } } 3.在Servlet中怎么样去控制 public class UserListServlet extends HttpServlet implements Servlet { public UserListServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); int pagesize = 5; String page = request.getParameter("page"); DB_User dbuser = new DB_User(); int count = dbuser.getCount(); // 记录总数 int totalPageNum = count / pagesize; // 计算总页数 // 如果纪录总数除以每页的显示个数,余数大于0,那么 // 总页数应该为商+1 if ((count % pagesize) > 0) { totalPageNum += 1; } if (page == null) { page = "1"; } request.setAttribute("totalPageNum", new Integer(totalPageNum)); Collection c = dbuser.getAll(pagesize, Integer.parseInt(page)); request.setAttribute("c", c); try { request.getRequestDispatcher("userlist.jsp").forward(request, response); } catch (Throwable t) { getServletContext().log(t.getMessage()); } 第三种是通过JavaBean来进行分页 1.建一个Java类 public class Page { //获得查询返回结果集 public Vector getResultSet() { DB_Conn db_conn=new DB_Conn(); ResultSet rs=null; try { db_conn.ConnectDB(); String sql="select *from goods"; rs=db_conn.sm.executeQuery(sql); Vector vector=new Vector(); while(rs.next()) { Goods goods=new Goods(); goods.setGoods_id(rs.getInt("goods_id")); goods.setGoods_name(rs.getString("goods_name")); goods.setTypeid(rs.getInt("typeid")); goods.setGoods_price(rs.getFloat("goods_price")); goods.setGoods_discount(rs.getFloat("goods_discount")); goods.setGoods_desc(rs.getString("goods_desc")); goods.setSupplier(rs.getString("supplier")); goods.setQty(rs.getInt("qty")); goods.setIspreferred(rs.getInt("ispreferred")); goods.setGoods_pic(rs.getString("goods_pic")); vector.addElement(goods); } return vector; } catch(SQLException SqlE) { SqlE.printStackTrace(); return null; } catch(Exception e) { e.printStackTrace(); return null; } finally { db_conn.CloseDB(); } } public String int2str(int id) { String new_str=""; if(id==0) { new_str="No"; } if(id==1) { new_str="Yes"; } return new_str; } 2.一个JavaBean类封装是一个属性 public class Goods { private int goods_id;// 对应于商品表中字段goods_id private String goods_name;// 对应于商品表中字段goods_name private int typeid;// 对应于商品表中字段typeid private float goods_price;// 对应于商品表中字段goods_price private float goods_discount;// 对应于商品表中字段goods_discount private String goods_desc;// 对应于商品表中字段goods_desc private String supplier;// 对应于商品表中字段supplier private int qty;// 对应于商品表中字段qty private int ispreferred;// 对应于商品表中字段ispreferred private String goods_pic;// 对应于商品表中字段goods_pic private int goods_number;// 中间变量,用于存储商品的数量 private double goods_amount;// 中间变量,用于存储商品的消费额 // 类的构造函数 public Goods() { } // 获取商品的编号 public int getGoods_id() { return goods_id; } // 设置商品的编号 public void setGoods_id(int goods_id) { this.goods_id = goods_id; } // 获取商品的名称 public String getGoods_name() { return goods_name; } // 设置商品的名称 public void setGoods_name(String goods_name) { this.goods_name = goods_name; } // 获取商品的类别编号 public int getTypeid() { return typeid; } // 设置商品的类别编号 public void setTypeid(int typeid) { this.typeid = typeid; } // 获取商品的价格 public float getGoods_price() { return goods_price; } // 设置商品的价格 public void setGoods_price(float goods_price) { this.goods_price = goods_price; } // 获取商品的折扣率 public float getGoods_discount() { return goods_discount; } // 设置商品的折扣率 public void setGoods_discount(float goods_discount) { this.goods_discount = goods_discount; } // 获取商品的描述信息 public String getGoods_desc() { return goods_desc; } // 设置商品的描述信息 public void setGoods_desc(String goods_desc) { this.goods_desc = goods_desc; } // 获取商品的生产制造商 public String getSupplier() { return supplier; } // 设置商品的生产制造商 public void setSupplier(String supplier) { this.supplier = supplier; } // 获取商品的库存数量 public int getQty() { return qty; } // 设置商品的库存数量 public void setQty(int qty) { this.qty = qty; } // 获取该商品是否为推荐商品 public int getIspreferred() { return ispreferred; } // 设置该商品是否为推荐商品 public void setIspreferred(int ispreferred) { this.ispreferred = ispreferred; } // 获取商品图片对应字符串 public String getGoods_pic() { return goods_pic; } // 设置商品图片对应字符串 public void setGoods_pic(String goods_pic) { this.goods_pic = goods_pic; } // 获取商品的数量 public int getGoods_number() { return goods_number; } // 设置商品的数量 public void setGoods_number(int goods_number) { this.goods_number = goods_number; } // 获取商品的消费额 public double getGoods_amount() { return goods_amount; } // 设置商品的消费额 public void setGoods_amount(double goods_amount) { this.goods_amount = goods_amount; } 3.一个负责接受的数据的JSP页面进行分页 <%@ page contentType="text/html;charset=UTF-8"%> <%@ page import="java.util.Vector"%> <%@ page import="java.lang.*"%> <jsp:directive.page import="com.ambow.xmk.page.Entity.Goods;"/> <jsp:useBean id="page_sep" class="com.ambow.xmk.page.Entity.Page" scope="session"/> <jsp:useBean id="db_type" class="com.ambow.xmk.page.Entity.DB_type" scope="session"/> <%! int intPageSize=4; //每页显示的记录数 int currPageBegin; //起始记录索引 int intPageCount; //总页数 int intPage; //待显示页码 String strPage; //用户请求页码 %> <% Goods goods=new Goods(); Vector vector=new Vector(); vector=page_sep.getResultSet(); //取得待显示页码 strPage = request.getParameter("pagenumber"); if(strPage==null) { //表明在QueryString中没有pagenumber这一个参数,此时显示第一页数据 intPage = 1; } else { //将字符串转换成整型 intPage = Integer.parseInt(strPage); if(intPage<1) intPage = 1; } //计算总页数 intPageCount = (vector.size()+intPageSize-1)/ intPageSize; //调整待显示的页码 if(intPage>intPageCount) intPage = intPageCount; //计算每一页的起始记录索引 currPageBegin =intPage*intPageSize-intPageSize; %> <table align=center border=1 cellspacing=0 width=90%> <tr bgcolor="#ffccff"> <td align=center>商品名称td><td>商品类别td> <td align=center>商品价格td><td>商品折扣率td> <td align=center>商品描述td><td>生产制造商td> <td align=center>库存量td><td align=center>是否推荐商品td> <td align=center>商品图片td>tr> <% for(inti=currPageBegin;i { goods=(Goods)vector.elementAt(i); %> <tr bgcolor="#f0ffff"> <td align=center><font size=2> <%=goods.getGoods_name()%>font>td> <td align=center><font size=2> <%=db_type.getTypename(goods.getTypeid())%>font>td> <td align=center><font size=2> <%=goods.getGoods_price()%>font>td> <td align=center><font size=2> <%=goods.getGoods_discount()%>font>td> <td align=left><font size=2> <%=goods.getGoods_desc()%>font>td> <td align=center><font size=2> <%=goods.getSupplier()%>font>td> <td align=center><font size=2> <%=goods.getQty()%>font>td> <td align=center><font size=2> <%=page_sep.int2str(goods.getIspreferred())%>font>td> <td align=center> <img src=<%=goods.getGoods_pic()%> width=50 height=50>td>tr> <% } %> <br> <table align=center> <tr><td align=right> 第<%=intPage%>页 共<%=intPageCount%>页 <% //以下是分页的“上一页”“下一页”,有上一页就有链接,没有就为文字,下一页同理%> <% if(intPage>1){ %> <a href="page_sep.jsp?pagenumber=<%=intPage-1%>">上一页a> <% }else{ %> 上一页 <%}%> <% if(intPage <a href="page_sep.jsp?pagenumber=<%=intPage+1%>">下一页a> <% }else{ %> 下一页 <%}%> tr> center> 第四种分页技术 1.Jsp中的调用 <%@ page contentType="text/html;charset=gb2312"%> <br> <h3> <center> 万能分页测试 h3> <hr color="#000032" size=2 width=75%> <br> <table align=center> <tr> <td align=center> 输入分页SQL: td> <td align=center> <form action="pagetoall.jsp"method="post"> <input type="text" name="sqlcmd" size=50> td> tr> <tr> <td align=center colspan=2> <input type="submit"name="submit" value="分页显示"> td> tr> 2. 处理分页的过程 <%@ page contentType="text/html;charset=UTF-8"%> <%@ page import="java.util.Vector"%> <%@ page import="java.lang.*"%> <jsp:directive.page import="com.ambow.xmk.page.Entity.Goods;"/> <jsp:useBean id="page_sep" class="com.ambow.xmk.page.Entity.Page" scope="session"/> <jsp:useBean id="db_type" class="com.ambow.xmk.page.Entity.DB_type" scope="session"/> <%! int intPageSize=4; //每页显示的记录数 int currPageBegin; //起始记录索引 int intPageCount; //总页数 int intPage; //待显示页码 String strPage; //用户请求页码 %> <% Goods goods=new Goods(); Vector vector=new Vector(); vector=page_sep.getResultSet(); //取得待显示页码 strPage = request.getParameter("pagenumber"); if(strPage==null) { //表明在QueryString中没有pagenumber这一个参数,此时显示第一页数据 intPage = 1; } else { //将字符串转换成整型 intPage = Integer.parseInt(strPage); if(intPage<1) intPage = 1; } //计算总页数 intPageCount = (vector.size()+intPageSize-1)/ intPageSize; //调整待显示的页码 if(intPage>intPageCount) intPage = intPageCount; //计算每一页的起始记录索引 currPageBegin =intPage*intPageSize-intPageSize; %> <table align=center border=1 cellspacing=0 width=90%> <tr bgcolor="#ffccff"> <td align=center>商品名称td><td>商品类别td> <td align=center>商品价格td><td>商品折扣率td> <td align=center>商品描述td><td>生产制造商td> <td align=center>库存量td><td align=center>是否推荐商品td> <td align=center>商品图片td>tr> <% for(int i=currPageBegin;i { goods=(Goods)vector.elementAt(i); %> <tr bgcolor="#f0ffff"> <td align=center><font size=2> <%=goods.getGoods_name()%>font>td> <td align=center><font size=2> <%=db_type.getTypename(goods.getTypeid())%>font>td> <td align=center><font size=2> <%=goods.getGoods_price()%>font>td> <td align=center><font size=2> <%=goods.getGoods_discount()%>font>td> <td align=left><font size=2> <%=goods.getGoods_desc()%>font>td> <td align=center><font size=2> <%=goods.getSupplier()%>font>td> <td align=center><font size=2> <%=goods.getQty()%>font>td> <td align=center><font size=2> <%=page_sep.int2str(goods.getIspreferred())%>font>td> <td align=center> <img src=<%=goods.getGoods_pic()%> width=50 height=50>td>tr> <% } %> <br> <table align=center> <tr><td align=right> 第<%=intPage%>页 共<%=intPageCount%>页 <% //以下是分页的“上一页”“下一页”,有上一页就有链接,没有就为文字,下一页同理%> <% if(intPage>1){ %> <a href="page_sep.jsp?pagenumber=<%=intPage-1%>">上一页a> <% }else{ %> 上一页 <%}%> <% if(intPage <a href="page_sep.jsp?pagenumber=<%=intPage+1%>">下一页a> <% }else{ %> 下一页 <%}%> tr> center> 1.5根据不同的DB来实现分页技术 1.1 OracleDB分页 Oracle中获得当前页面数据的SQL片段代码; Select * from ( Select a.*,rownum rcfrom ( select * from student order by student_numberasc ) a where rownum<=endrow ) b whererc>=statrow 其中,startrow、endrow 分别为当钱页面的起始行与终止行,具体应用是可用start=(intpage-1)*perpagesize+1,endrow=intpage*perpagesize进行计算 1.2 DB2 DB 分页 Select * from ( select rownumber() over() as rc,a.*from ( select * from student order by student_numberasc )as a )where rc betweenstartrow and endrow 1.3 SQL Server 2000DB 分页 Select topperpagesize * from student where ( student_id not int ( Select top perpagesize*intpage student_id fromstudent order by student_id order student_id ) ) Order by Student_id 1.4 SQL Server 2005DB 分页 利用2005 的新功能 可以获得更好的分页查询性能并简化SQL 语句的编写。 Select * from ( selectstudent_id,row_number() over(order by student_name)as curr from student )as t wheret.curr>=startrow and t.curr<=endrow 1.5 MySQl DB 分页 MySQL数据库的生气了最为简单 ,以下为在MySQL数据库获得当前页数的SQl片段代码 Select * fromstudent limit startrow,perpagesize 其中,startrow 为当前页的起始页,具体应用是也可用startrow=(intpage-1)*perpagesize+1进行计算,而perpagesize为每页显示记录数量。 1.6 PostgreSQL 数据库分页 数据库分页比较简单,以下是代码片段 Select * fromstudent limit perpagesize offset startrow 其中,perpagesize,startrow的计算MYSQL中是一致的