JSP通用查询处理与分页显示
铁树
tieshu
2006年4月2日星期日
(注:涉及的源码可通过Email:rngguliu@163.com获取)
1 基本思想
鉴于JSP开发中多次用到查询与分页显示的功能,故将查询处理及分页显示进行了统一设计和功能封装,在一定程度上加快了开发进程,提高了编码效率,减少了重复性劳动,提高了代码重用度。
流程如下。
由上述流程可以看出,整个查询及分页显示只检索一次数据库,也就是只建立一次数据库连接。翻页显示时,不再进行查询。从一定程度上减轻了系统的负担,同时翻页速度也得到提高。
本设计的注意点是,对于session的变量名的处理,不要重复,以免发生混乱,约定采用”表名”和相应操作的组合,见示例程序。
2 两个重要的类
这两个类的调用接口及易掌握,只需简单的调用几个方法,即可实现完美的分页显示。
这两个类相对独立而实用,可单独在其他程序中进行调用。如果将这二者进行结合,可实现任意对象集的完美分页显示。
2.1 Page分页处理类
为了简化分页功能的处理,特将分页有关的处理封装在此类中。输入参数为某一数据集(或对象集合)、每页显示的记录数及要显示的页码,返回要显示的记录集。
构造函数概览 | |
|
|
|
|
|
|
方法概览 | |
|
|
|
|
|
|
|
|
|
|
|
|
public Page(java.util.List data, int itemsPerPage)
构造函数1,List数据集 设置数据集和每页显示多少个记录同时计算出总页数和总记录数,对当前页码置1
参数:
data
- 要显示的数据集
itemsPerPage
- 每页显示多少个记录
public Page(java.util.Vector data, int itemsPerPage)
构造函数2,Vector数据集 设置数据集和每页显示多少个记录同时计算出总页数和总记录数,对当前页码置1
参数:
data
- 要显示的数据集
itemsPerPage
- 每页显示多少个记录
public Page(java.lang.Object data, int itemsPerPage)
构造函数3,Object数据集 设置数据集和每页显示多少个记录同时计算出总页数和总记录数,对当前页码置1
参数:
data
- 要显示的数据集
itemsPerPage
- 每页显示多少个记录
public int getCurrentRecord()
返回值: 当前记录编号
。
public java.util.List showPage(String pageNum)
根据页码找出要显示的数据集
参数:
pageNum
- 指定的页码
返回值: 要显示的数据集
getValidFoot
public String getValidFoot(String url, String pagePara)
//取得分页的页脚信息1,自动隐藏无效链接
返回值: 分页的页脚信息
public String getValidFoot(String url, String pagePara, String otherPara)
//取得分页的页脚信息1,自动隐藏无效链接
返回值: 分页的页脚信息
getAllFoot
public String getAllFoot(String url, String pagePara)
//取得分页的页脚信息2,显示无效链接
返回值: 分页的页脚信息
public String getAllFoot(String url, String pagePara, String otherPara)
//取得分页的页脚信息3,显示无效链接,处理关联子表的情况
返回值: 分页的页脚信息
2.2 Face 界面显示类
为了界面的统一及灵活而简易的设置,特封装此类.调用接口简易实用。
构造函数概览 | |
|
|
方法概览 | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//弹出对话框,链接列(例如:删除) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
构造函数细节 |
public Face()
方法细节 |
public void setStyle(int StyleIndex)
//设置显示样式,内置了几种颜色方案(感谢ezpj2005@yahoo.com.cn朋友); 1 为默认样式,也可以自己设定颜色方案
参数: StyleIndex
-
public String Table() 表头
public String Table(String width) 带参数表头
参数:
width
- //表格宽度
public String TableE() 表尾
public String TR()
普通行显示风格(例如添加、修改、查询界面时调用,或者表头、分页脚注等部分调用)
public String TRB() 浏览行显示风格(浏览、查询结果显示时调用)
public String TRE() //行尾标志
public String TH() 表格头显示风格 //显示空格
public String TH(String label) 表格头显示风格
参数:
label
- //要显示的内容
public String TH(int colspan, String label) 表格头显示风格
参数:
label
- //要显示的内容
colspan
- //跨列显示
public String TH(String width, String label)
参数:
width
- //列宽度
label
- //要显示的内容
public String TH(String width, int colspan, String label)
参数:
width
- //列宽度
colspan
- //跨列显示
label
- //要显示的内容
public String THI(String value,
String label)
//链接列
参数:
label
- //显示内容
value
- //要链接的内容
public String THI(String width, int colspan, String value, String label)
参数:
width
- //列宽度
colspan
- //跨列显示
value
- //要链接的内容
label
- //要显示的内容
public String TD() 表格列显示风格 //显示空格
public String TD(String label) 表格列显示风格
参数:
label
- //要显示的内容
public String TD(int colspan, String label) 表格列显示风格
参数:
label
- //要显示的内容
colspan
- //跨列显示
public String TD(int colspan, String label, String align) 表格列显示风格
参数:
label
- //要显示的内容
colspan
- //跨列显示
align
- //对齐方式
public String TD(String width, String label)
参数:
width
- //列宽度
label
- //要显示的内容
public String TD(String width, int colspan, String label)
参数:
width
- //列宽度
colspan
- //跨列显示
label
- //要显示的内容
public String TDI(String value, String label) //链接列
参数:
label
- //显示内容
value
- //要链接的内容
public String TDI(String value, String label, String method) //链接列
参数:
label
- //显示内容
value
- //要链接的内容
method
- //打开方式 :_blank,_parent,_self,_top
public String TDI(String width, int colspan, String value, String label)
参数:
width
- //列宽度
colspan
- //跨列显示
value
- //要链接的内容
label
- //要显示的内容
public String TDD(String value, String label) //弹出对话框,链接列(例如:删除)
参数:
value
- //要链接的内容
label
- //要显示的内容
public String TDD(String value, String label, String msg)
//弹出对话框,链接列(例如:删除)
参数:
value
- //要链接的内容
label
- //要显示的内容
msg
- //弹出的对话框的内容
2.3 对象集分页显示实例
<%@ page import="general.*" %>
<%@ page import="java.util.List” %>
<jsp:useBean id="bean" class="general.testBean.BookBean" />
<%
String pagenum = request.getParameter("pageNum"); //要显示的当前页
int itemsPerPage = 10;//设置每页显示的记录数
java.util.Vector v = bean.GetBookByString(" 1=1 ");//可输入指定的查询条件
//v中存放的是book对象集合,具有名称,价格等属性
Page p = new Page(v, itemsPerPage);
List display = p.showPage(pagenum); //获取要显示的集合列表
Face fc =new Face();//界面显示类
fc.setStyle(1); //设置显示样式
String face="";//输出的内容字符串
face += fc.Table();//建立一个表格
face += fc.TR();//普通行风格
face += fc.TH("序号");//标题显示,自动编号
face += fc.TH("书名");
face += fc.TH("简介");
face += fc.TH("出版社");
face += fc.TH("作者");
face += fc.TH("价格");;
face += fc.TH();//对应“修改”
face += fc.TH();//对应“删除”
face += fc.TRE();//行结束
int c=p.getCurrentRecord();//获取当前记录编号
for (int i = 0; i < display.size(); i++) {
Book b= (Book)display.get(i);
face += fc.TRB();//浏览行风格
face += fc.TD(String.valueOf(++c));
face += fc.TDI("book_detail.jsp?id="+b.getId(),b.getTitle(),"_blank");
face += fc.TD(b.getMemo());
face += fc.TD(b.getPress());
face += fc.TD(b.getAuthor());
face += fc.TD(String.valueOf(b.getPrice()));
face += fc.TDI("book_modify.jsp?id="+b.getId(),"修改");
face += fc.TDD("book_del.jsp?id="+b.getId(),"删除");//会弹出确认对话框
face += fc.TRE();
}
face += fc.TR();//获取分页链接
face += fc.TD(8,p.getAllFoot("book_browse.jsp","pageNum"),"center");
face += fc.TRE();
face += fc.TableE();
out.println(face);
%>
3 实例
本实例设计采用值对象模式,例如对书基本信息的维护,采用Mysql数据库。
本实例中涉及的所有源码均可通过Email:rngguliu@163.com获取。
3.1 数据表
sql:
CREATE TABLE BOOK
(
ID INT(10) NOT NULL AUTO_INCREMENT,
TITLE VARCHAR(50),
MEMO TEXT,
AUTHOR VARCHAR(50),
PRESS VARCHAR(50),
PRICE DECIMAL(6,2),
PRIMARY KEY (ID)
)
TYPE = INNODB;
3.2 数据库操作类
采用连接池技术。
资源配置文件:db.property;类DBConn和DBConnectionManager,主要实现的方法如下。
l public DBConn()//构造函数,创建执行的一般容器Statement实例
l public ResultSet executeQuery(String sql) //执行SQL语句,返回字段集
l public int executeUpdate(String sql)// 执行SQL更新语句,返回受影响的记录数
l public void close()//关闭连接
该方法的实现较为普遍,在此不再详述。
3.3 值对象模式
基类:又称为值对象。为了方便表示数据,我们把每个数据表都做成一个值对象的类,这样在JavaBean和JSP页面之间传递数据时可以通过值对象来进行,主要用于操作类的调用。在值对象中,每个属性对应数据表的一个字段,并且他们的数据类型是对应的。并且为每个属性都提供了getter和setter方法,这样,就为在JavaBean和JSP页面之间传递参数提供了方便。
操作类:把和业务操作相关的逻辑都封装在这里。它封装了和值对象所对应的表的所有相关操作,如添加、修改、删除、查询等。
JavaBean:JavaBean体系结构是一个全面地基于组件的标准模型。JavaBean组件是Java类,这些类遵循一个接口格式,以便于使方法命名、底层行为以及继承或实现的行为能够把类看作标准的JavaBean组件进行构造。
JavaBean具有以下特性:
l 可以实现代码的重复利用。
l 易维护性、易使用性、易编写性。
l 可以在支持Java的任何平台上工作,而不需要重新编译。
在本实例中,采用JSP+JavaBean技术。
JSP+JavaBean的数据传递关系:
这种模式中,JSP作为视图,同时也有部分控制器的功能,JavaBean组件作为模型和控制器组件。当HTTP请求到达JSP时,它首先设置JavaBean组件的属性,然后调用JavaBean组件的方法,JavaBean组件通过连接数据库来执行业务逻辑,最后JavaBean组件把执行的结果返回给JSP显示。
3.4 基类
package general;
/**
* @author tieshu
*/
public class Book {
private int id;//书ID
private String title;//书标题
private String memo;//书简介
private String author;//作者
private String press;//出版社
private double price;//价格
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
3.5 操作类
package general;
import general.database.DBConn;
import java.sql.*;
import java.util.Vector;
import general.common.*;
/**
* @author tieshu
*/
public class BookBean {
public int addBook(Book obj) {//添加一条记录
int result;
try {
DBConn dbConn = new DBConn();
StringBuffer sql = new StringBuffer();
sql.append("insert into book(title,memo,author,press,price) values(");
sql.append("'" + ParamUtils.filterByNone(obj.getTitle()) + "',");
sql.append("'" + ParamUtils.filterByNone(obj.getMemo()) + "',");
sql.append("'" + ParamUtils.filterByNone(obj.getAuthor()) + "',");
sql.append("'" + ParamUtils.filterByNone(obj.getPress()) + "',");
sql.append(obj.getPrice());
sql.append(")");
result = dbConn.executeUpdate(sql.toString());
dbConn.close();
} catch (Exception e) {
e.printStackTrace();
result=0;
}
return result;
}
public int modifyBook(Book obj) {//修改
int result;
try {
DBConn dbConn = new DBConn();
StringBuffer sql = new StringBuffer();
sql.append("update book set ");
sql.append("title='" + ParamUtils.filterByNone(obj.getTitle()) + "',");
sql.append("memo='" + ParamUtils.filterByNone(obj.getMemo()) + "',");
sql.append("author='" + ParamUtils.filterByNone(obj.getAuthor()) + "',");
sql.append("press='" + ParamUtils.filterByNone(obj.getPress()) + "',");
sql.append("price=" + obj.getPrice());
sql.append(" where id=" + obj.getId());
result = dbConn.executeUpdate(sql.toString());
dbConn.close();
} catch (Exception e) {
result=0;
e.printStackTrace();
}
return result;
}
public int delBook(String id) {//删除
try {
DBConn dbConn = new DBConn();
int result = dbConn.executeUpdate("delete from book where id=" + id);
dbConn.close();
return result;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public Book getBookById(String id) {//根据id得到唯一的一条记录,常用于修改调用
try {
DBConn dbConn = new DBConn();
StringBuffer sql = new StringBuffer();
sql.append("select * from book where id=" + id);
ResultSet rs = dbConn.executeQuery(sql.toString());
Book temp = new Book();
while (rs.next()) {
temp.setId(rs.getInt("id"));
temp.setTitle(ParamUtils.filterByNone(rs.getString("title")));
temp.setMemo(ParamUtils.filterByNone(rs.getString("memo")));
temp.setAuthor(ParamUtils.filterByNone(rs.getString("author")));
temp.setPress(ParamUtils.filterByNone(rs.getString("press")));
temp.setPrice(rs.getDouble("price"));
dbConn.close();
return temp;
}
dbConn.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Book getBookById1(String id) {//根据id得到唯一的一条记录,常用于查询调用
try {
DBConn dbConn = new DBConn();
StringBuffer sql = new StringBuffer();
sql.append("select * from book where id=" + id);
ResultSet rs = dbConn.executeQuery(sql.toString());
Book temp = new Book();
while (rs.next()) {
temp.setId(rs.getInt("id"));
temp.setTitle(ParamUtils.filterBySpace(rs.getString("title")));
temp.setMemo(ParamUtils.filterBySpace(rs.getString("memo")));
temp.setAuthor(ParamUtils.filterBySpace(rs.getString("author")));
temp.setPress(ParamUtils.filterBySpace(rs.getString("press")));
temp.setPrice(rs.getDouble("price"));
dbConn.close();
return temp;
}
dbConn.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* lrg//根据查询条件得到结果集合
* @param condition不带条件关键字where
* @return 满足条件的结果集合
* @throws Exception
*/
public Vector GetBookByString(String condition) {
try {
String sql = "select * from book ";
if (condition != null && (!condition.trim().equals(""))) {
sql += " where " + condition;
}
sql += " order by id desc";
DBConn dbConn = new DBConn();
ResultSet rs = dbConn.executeQuery(sql);
Vector ret = new Vector();
while (rs.next()) {
Book temp = new Book();
temp.setId(rs.getInt("id"));
temp.setTitle(ParamUtils.filterBySpace(rs.getString("title")));
temp.setMemo(ParamUtils.filterBySpace(rs.getString("memo")));
temp.setAuthor(ParamUtils.filterBySpace(rs.getString("author")));
temp.setPress(ParamUtils.filterBySpace(rs.getString("press")));
temp.setPrice(rs.getDouble("price"));
ret.add(temp);
}
dbConn.close();
return ret;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
3.6 查询页面book_query.jsp
关键代码如下:
<form id="form1" name="form1" method="post" action="book_dispose.jsp?query_sql=new">
<table width="480" border="1" align="center" cellpadding="2" cellspacing="1"bordercolordark="#94CCF6"bordercolorlight="#fefefe">
<tr>
<td width="80" bgcolor="#C8E1FA"> 书名</td>
<td bgcolor="#D1E8FC"><input name="title" type="text" size="30" /> </td></tr>
<tr><td>作者</td>
<td><input name="author" type="text" id="author" size="30" /></td> </tr>
<tr> <td bgcolor="#C8E1FA">出版社</td>
<td bgcolor="#D1E8FC"><input name="press" type="text" size="30" /></td></tr>
<tr><td>简介</td>
<td><textarea name="memo" cols="30" rows="5" id="memo"></textarea></td></tr>
</table>
<table width="200" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td><img style="cursor:pointer " src="images/search.gif" width="44" height="21"onClick="form1.submit()"/></td>
<td><img style="cursor:pointer " src="images/reset.gif" width="44" height="21"onClick="form1.reset()"/></td>
<td height="35"><img style="cursor:pointer " src="images/back.gif" width="44" height="21"onclick="history.go(-1)"/></td>
</tr>
</table>
</form>
3.7 查询处理页面book_dispose.jsp
关键代码如下:
<%@ page language="java" contentType="text/html;charset=gb2312"%>
<%@ page import="general.common.ParamUtils"%>
<html><head></head><body>
<jsp:useBean id="bean" class="general.testBean.BookBean" />
<% StringBuffer condition = new StringBuffer();
String query_sql = ParamUtils.getValue(request, "query_sql");
//如果是来自query页面或者直接浏览的话,则执行以下语句,进行重新查询,
//否则直接从session里取查询条件,如常用于修改、删除后的返回界面。
if (query_sql != null) {
String title = ParamUtils.getValue(request, "title");
String memo = ParamUtils.getValue(request, "memo");
String author = ParamUtils.getValue(request, "author");
String press = ParamUtils.getValue(request, "press");
//以下若查询条件为空,则不做处理
condition.append(" 1=1 ");
if (title != null) {
condition.append(" and title like '%" + title + "%' ");
}
if (memo != null) {
condition.append(" and memo like '%" + memo + "%' ");
}
if (author != null) {
condition.append(" and author like '%" + author + "%' ");
}
if (press != null) {
condition.append(" and press like '%" + press + "%' ");
}
} else {//不是来自query页面的分页处理,
String sc=String.valueOf(session.getAttribute("book_sql"));
if (sc!=null&&(!sc.equals("null"))){
condition.append(sc);
}
}
//根据获得的查询条件取得结果集,并赋予session的属性(建议以表名命名属性)
try {
java.util.Vector v = bean.GetBookByString(condition.toString());
session.setAttribute("book", v);
session.setAttribute("book_sql", condition.toString());
response.sendRedirect("book_list.jsp");
} catch (Exception e) {
e.printStackTrace();
out.println("<script>window.alert('查找失败!');history.go(-1);</script>");
out.println(e.getMessage());
}
%>
</body>
</html>
3.8 分页显示页面book_list.jsp
关键代码如下:
<%@ page import="general.*" %>
<%@ page import="java.util.List" %>
<%
String pagenum = request.getParameter("pageNum"); //要显示的当前页
int itemsPerPage = 10;//设置每页显示的记录数
List v= (List)session.getAttribute("book");
//session(book)中存放的是book对象集合,具有名称,价格等属性
Page p = new Page(v, itemsPerPage);
List display = p.showPage(pagenum); //获取要显示的集合列表
Face fc =new Face();//界面显示类
fc.setStyle(1); //设置显示样式
String face="";//输出的内容字符串
face += fc.Table();//建立一个表格
face += fc.TR();//普通行风格
face += fc.TH("序号");//标题显示,自动编号
face += fc.TH("书名");
face += fc.TH("简介");
face += fc.TH("出版社");
face += fc.TH("作者");
face += fc.TH("价格");;
face += fc.TH();//对应“修改”
face += fc.TH();//对应“删除”
face += fc.TRE();//行结束
int c=p.getCurrentRecord();//获取当前记录编号
for (int i = 0; i < display.size(); i++) {
Book b= (Book)display.get(i);
face += fc.TRB();//浏览行风格
face += fc.TD(String.valueOf(++c));
face += fc.TDI("book_detail.jsp?id="+b.getId(),b.getTitle(),"_blank");
face += fc.TD(b.getMemo());
face += fc.TD(b.getPress());
face += fc.TD(b.getAuthor());
face += fc.TD(String.valueOf(b.getPrice()));
face += fc.TDI("book_modify.jsp?id="+b.getId(),"修改");
face += fc.TDD("book_del.jsp?id="+b.getId(),"删除");//会弹出确认对话框
face += fc.TRE();
}
face += fc.TR();//获取分页链接
face += fc.TD(8,p.getAllFoot("book_list.jsp","pageNum"),"center");
face += fc.TRE();
face += fc.TableE();
out.println(face);
%>
3.9 删除页面book_del.jsp
关键代码如下:
<jsp:useBean id="p" class="general.testBean.Book" scope="page">
<jsp:setProperty name="p" property="*"></jsp:setProperty> </jsp:useBean>
<jsp:useBean id="pBean" class="general.testBean.BookBean" scope="page"/>
<%
String temp=request.getParameter("id");
try{
int result=pBean.delBook(temp);
if(result >0){
out.println("<script> location.href='book_dispose.jsp'</script>");
} else{
out.println("<script>window.alert('删除失败!');history.go(-1);</script>");
}
}
catch(Exception e)
{
e.printStackTrace();
out.println("<script>window.alert('删除失败!');history.go(-1);</script>");
}
%>
3.10 修改页面book_modify.jsp
关键代码如下:
<%!String temp="";%>
<%temp=request.getParameter("id");
try{
b=bean.getBookById(temp);
if (b==null){
out.println("该记录不存在!");
out.close();
}}catch(Exception e)
{
e.printStackTrace();
out.println(e.getMessage());
out.close();
}
%>
<form id="form1" name="form1" method="post" action="book_modifysave.jsp">
<table width="480" border="1" align="center" cellpadding="2" cellspacing="1"bordercolordark="#94CCF6"bordercolorlight="#fefefe">
<tr>
<td width="80" bgcolor="#C8E1FA"> 标 题</td> <td bgcolor="#D1E8FC">
<input name="id" type="hidden" value="<%=temp%>"/>
<input name="title" type="text" value="<%=b.getTitle()%>" size="60" /></td>
</tr> <tr> <td bgcolor="#C8E1FA">作者</td>
<td><input name="author" type="text" value="<%=b.getAuthor()%>" size="60" /></td>
</tr>
<tr><td bgcolor="#C8E1FA">出版社</td> <td bgcolor="#D1E8FC">
<input name="press" type="text" value="<%=b.getPress()%>" size="60" /></td>
</tr> <tr> <td bgcolor="#C8E1FA">价格</td>
<td><input name="price" type="text" value="<%=b.getPrice()%>" size="60"/></td>
</tr> <tr> <td bgcolor="#C8E1FA">内 容</td>
<td><textarea name="memo" cols="60" rows="5" ><%=b.getMemo()%></textarea></td>
</tr> </table>
<table width="200" border="0" align="center" cellpadding="0" cellspacing="0">
<tr><td><img style="cursor:pointer " src="images/save.gif" width="44" height="21"onclick="if(Validator.Validate(form1,2)){form1.submit();}"/></td>
<td><img style="cursor:pointer " src="images/reset.gif" width="44" height="21"onclick="form1.reset()"/></td>
<td height="35"><img style="cursor:pointer " src="images/back.gif" width="44" height="21"onclick="history.go(-1)"/></td>
</tr>
</table>
</form>
3.11 保存修改页面book_modifysave.jsp
关键代码如下:
<jsp:useBean id="p" class="general.testBean.Book" scope="page">
<jsp:setProperty name="p" property="*"></jsp:setProperty></jsp:useBean>
<jsp:useBean id="pBean " class="general.testBean.BookBean" scope="page"/>
<%
int result;
try{
result = pBean.modifyBook(p);
if(result >0){
out.println("<script> location.href='book_dispose.jsp'</script>");
} else{
out.println("<script>window.alert('修改失败!');history.go(-1);</script>");
}
}
catch(Exception e)
{
e.printStackTrace();
out.println("<script>window.alert('修改失败!');history.go(-1);</script>");
}
%>
3.11 其他页面book_add.jsp
其他页面如book_add.jsp,book_addsave.jsp,book_detail.jsp等的代码不一一列出,请借鉴查询、修改和保存修改等页面的代码。
本实例中涉及的所有源码均可通过Email:rngguliu@163.com获取。
4 效果图
本效果图方案参考了ezpj2005@yahoo.com.cn朋友的成果,特表示感谢!
4.1 效果图1