应一位朋友的要求。今晚也是我的周末,所以做了个分页。虽然网上相似文章比较多,不过我做分页的时候,看网上的文章也难做得出来。第一次写博客,希望看了我这篇《Struts1.2实现MySQL数据库分页》的还不能做出一个分页的朋友拍我砖头。没办法,文章写作太差了。
我的平台是:Eclipse3.2
MyEclipse5.5 Tomcat5.5 MySql5.0
第一步:创建数据库:
这没什么难的,用下面的脚本就OK了。
CREATE
DATABASE
page
;
use
page
;
CREATE
TABLE
`product` (
`id`
varchar
(11)
NOT
NULL
,
`sortid`
varchar
(11)
NOT
NULL
,
`
name
`
varchar
(50)
NOT
NULL
,
`price`
double
NOT
NULL
,
`saleprice`
double
NOT
NULL
,
`descript` text
NOT
NULL
,
`contents` text
NOT
NULL
,
`saledate`
varchar
(255)
NOT
NULL
,
`salecount`
int
(11)
default
NULL
,
`image` text,
PRIMARY
KEY
(`id`)
) ENGINE=InnoDB
DEFAULT
CHARSET=utf8;
第二步:创建一个项目
创建一个项目
,
项目名为
”strutsPage”,
导入
Struts1.2
,
Struts
的包采用默认,引用
MySql
的驱动,要是没有驱动的话,请到
http://download.csdn.net/source/400716
这下载。
下面设置
web.xml
和
struts-config.xml
配置文件,我觉得直接
COPY
我的就好了。
web.xml
:文件里的内容如下,直接换上就
OK
了。基本是默认的。
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
web-app
xmlns
=
"http://java.sun.com/xml/ns/j2ee"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
version
=
"2.4"
xsi:schemaLocation
=
"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
<
servlet
>
<
servlet-name
>
action
</
servlet-name
>
<
servlet-class
>
org.apache.struts.action.ActionServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
config
</
param-name
>
<
param-value
>
/WEB-INF/struts-config.xml
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
debug
</
param-name
>
<
param-value
>
3
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
detail
</
param-name
>
<
param-value
>
3
</
param-value
>
</
init-param
>
<
load-on-startup
>
0
</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
action
</
servlet-name
>
<
url-pattern
>
*.do
</
url-pattern
>
</
servlet-mapping
>
<
welcome-file-list
>
<
welcome-file
>
index.jsp
</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
struts-config.xml
的内容如下:
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!
DOCTYPE
struts-config
PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd"
>
<
struts-config
>
<
data-sources
/>
<
form-beans
/>
<
global-exceptions
/>
<
global-forwards
/>
<
action-mappings
>
<
action
attribute
=
"productShowForm"
input
=
"/index.jsp"
name
=
"productShowForm"
path
=
"/productShow"
scope
=
"request"
type
=
"com.yourcompany.struts.action.ProductShowAction"
>
<
forward
name
=
"success"
path
=
"/index.jsp"
/>
</
action
>
</
action-mappings
>
<
message-resources
parameter
=
"com.yourcompany.struts.ApplicationResources"
/>
</
struts-config
>
第三步:创建包和数据库连接
在
SRC
下创建
dao , dbtool, vo,factory
四个包
在
dbtool
包里主要放访问
JDBC
数据库的连接类等。下面提供我用的
JavaBean
类。
DBConnection.java
的内容如下:
package com.yourcompany.dbtool;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
*
这是一个连接数据的单模式
* @author
树下无影
*
*/
public class DBConnection {
private static DBConnection instance;
private String driver;
private String url;
private String user;
private String password;
private DBConnection() throws Exception{
InputStream in=getClass().getClassLoader().getResourceAsStream(
"com/yourcompany/dbtool/database.properties");
Properties prop=new Properties();
prop.load(in);
driver=prop.getProperty("driver");
url=prop.getProperty("url");
user=prop.getProperty("user");
password=prop.getProperty("password");
try{
Class.forName(driver);
}catch(Exception e)
{
System.out.println("
数据库初始化出错
");
throw e;
}
System.out.println(driver+" "+url+" "+user+" "+password);
}
public static DBConnection getInstance(){
try{
if(instance==null){
instance=new DBConnection();
}
return instance;
}catch(Exception e){
System.out.println("
实例化单模子出错
");
return null;
}
}
public Connection getConnection()throws SQLException{
Connection con;
try{
con=DriverManager.getConnection(url, user, password);
}catch(SQLException e){
System.out.println("Connection
连接出错
");
throw e;
}
return con;
}
public void closeConnection(Connection con){
if(con!=null){
try{
con.close();
}catch(SQLException e)
{
System.out.println("
关闭
Connection
连接出错
");
}
}
}
}
这里用一个配置文件,
database.properties
里面存放数据库的
URL
、
Driver
、
Username
和
Password
等,修改成你本机的相应数据,能打开数据库就好。
database.properties
内容如下:
driver=org.gjt.mm.mysql.Driver
url=jdbc:mysql://localhost:3306/page
user=root
password=1234
下面是我用的数据库增删改查的
Bean-> DBbusiness.java
package com.yourcompany.dbtool;
import java.sql.*;
/**
*
这是一个连接数据库具有增删改查的
Bean
* @author
树下无影
*
*/
public class DBbusiness {
/*
*
定义连接参数等
*/
Connection conn = null;
PreparedStatement psps = null;
ResultSet rs = null;
public DBbusiness (){
}
/*
*
定义公用的
Connection
*/
public Connection getConn() {
try {
DBConnection db=DBConnection.getInstance();
Connection conx = db.getConnection();
return conx;
} catch (Exception e) {
System.out.println("Connection
连接出错
");
}
return null;
}
/*
*
获取数据
(
查询
)
方法
*/
public ResultSet getData(String sql) {
try {
conn = getConn();
psps = conn.prepareStatement(sql);
rs = psps.executeQuery();
} catch (Exception e) {
System.out.println("
查询数据库操作出错
");
}
return rs;
}
/*
*
定义插入数据和更新的方法
*/
public boolean insert(String sql) {
try {
conn = getConn();
psps = conn.prepareStatement(sql);
psps.executeUpdate();
return true;
} catch (Exception e) {
System.out.println("
数据库更新出错
");
}
return false;
}
/*
*
定义创建数据库和表的方法
*/
public boolean create(String sql) {
try {
conn = getConn();
psps = conn.prepareStatement(sql);
psps.execute();
return true;
} catch (Exception e) {
}
return false;
}
/*
*
定义关闭连接的方法
*/
public void allClose() {
try {
if (rs != null)
rs.close();
if (psps != null)
psps.close();
if (conn != null)
{
DBConnection db=DBConnection.getInstance();
db.closeConnection(conn);
}
} catch (Exception e) {
System.out.println("
数据库关闭操作出错
");
}
}
}
第四步:创建实体类
在
vo
包里,创建一个实体类,这步
COPY
过去就是。
Product.java
package com.yourcompany.vo;
public class Product {
String id;
String sortid;
String name;
String price;
String saleprice;
String descript;
String contents;
String saledate;
String salecount;
String image;
public Product(){}
public Product(String id,String sortid,String name,String price,
String saleprice,String descript,String contents,
String saledate,String salecount,String image){
this.id=id;
this.sortid=sortid;
this.name=name;
this.price=price;
this.saleprice=saleprice;
this.descript=descript;
this.contents=contents;
this.saledate=saledate;
this.salecount=salecount;
this.image=image;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public String getDescript() {
return descript;
}
public void setDescript(String descript) {
this.descript = descript;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getSalecount() {
return salecount;
}
public void setSalecount(String salecount) {
this.salecount = salecount;
}
public String getSaledate() {
return saledate;
}
public void setSaledate(String saledate) {
this.saledate = saledate;
}
public String getSaleprice() {
return saleprice;
}
public void setSaleprice(String saleprice) {
this.saleprice = saleprice;
}
public String getSortid() {
return sortid;
}
public void setSortid(String sortid) {
this.sortid = sortid;
}
}
第五步:创建接口,并创建相应的实现类
PageDao.java
接口里有两个方法
,
第一个方法是读取指定数据表的行数;第二个方法是读取数据表,并把信息放入一个
ArrayList
返回。看代码
package com.yourcompany.dao;
import java.util.ArrayList;
import java.util.List;
public interface PageDao {
public int getCount(String counSql);
public ArrayList getProduct(String sql);
}
创建接口好后,当然要创建实现类,
如下:
PageDaoImpl.java
package com.yourcompany.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import com.yourcompany.dbtool.DBbusiness;
import com.yourcompany.vo.Product;
/**
*
这是接口的实现类
* @author
树下无影
*
*/
public class PageDaoImpl implements PageDao {
/*
*
获取数据行数
* @see com.yourcompany.dao.PageDao#getCount(java.lang.String)
*/
public int getCount(String counSql){
int result=0;
DBbusiness db=new DBbusiness();
ResultSet rs= db.getData(counSql);
try {
rs.next();
result=rs.getInt(1);
/*while(rs.next()){
result=rs.getInt(1);
}*/
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("
读取数据总数失败
");
}finally{
db.allClose();
}
return result;
}
/*
*
读取数据表
*/
public ArrayList getProduct(String sql){
ArrayList arrayList=new ArrayList();
DBbusiness db=new DBbusiness();
ResultSet rs=db.getData(sql);
try {
while(rs.next()){
String id=rs.getString(1);
String sortid=rs.getString(2);
String name=rs.getString(3);
String price=rs.getString(4);
String saleprice=rs.getString(5);
String descript=rs.getString(6);
String contents=rs.getString(7);
String saledate=rs.getString(8);
String salecount=rs.getString(9);
String image=rs.getString(10);
Product productForm=new Product( id,sortid ,name, price,
saleprice ,descript, contents,
saledate,salecount,image);
arrayList.add(productForm);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("
数据库读取出错
");
}finally{
db.allClose();
}
return arrayList;
}
}
第六步:创建映射的工厂类:
这个类没什么解释,放在
factoyr
的包里
PageDaoFactory.java
package com.yourcompany.factory;
import com.yourcompany.dao.PageDao;
import com.yourcompany.dao.PageDaoImpl;
public class PageDaoFactory {
public static PageDao getPageDaoIntanse(){
return new PageDaoImpl();
}
}
第七步:分页处理类
呵呵,这么多步骤了还没进入正题,下面就开始讲和分页相关的。
在
dbtool
包里创建如下类:
PageBean.java
package com.yourcompany.dbtool;
import com.yourcompany.factory.PageDaoFactory;
public class PageBean {
/**
*
这是一个分页的类,因为
MySQL
数据库检索可以使用分页的
SQL
指令
*
所在在这里主要是处理出这样的指令
*
并获得相应的页数信息
*MySql
语句如下
:select * from test limit 10;
这句是从
1
到
10
的信息条数
*select * from test limit 10,5;
这句是第十条以后的五条
*/
int curr; //
当前页
int count; //
总页数
int size; //
每页显示数据数
int rows=0; //
数据的所有行数
boolean last; //
是否是最后一页
/**
*
构造器
* @param counSql
*/
public PageBean(String counSql) {
if (this.rows == 0) {//
获取所有的数据条数
this.rows = PageDaoFactory.getPageDaoIntanse().getCount(counSql);
}
this.curr=getCurr();
this.size = 5;//
设定页面显示数据大小
this.count = (int) Math.ceil((double) this.rows / this.size);//
获得页数
this.last=isLast();
}
public PageBean(String counSql,int size){
if (this.rows == 0) {//
获取所有的数据条数
this.rows = PageDaoFactory.getPageDaoIntanse().getCount(counSql);
}
this.curr=getCurr();
this.size = size;//
设定页面显示数据大小
this.count = (int) Math.ceil((double) this.rows / this.size);
this.last=isLast();
}
public PageBean(String counSql,int curr,int size){
if (this.rows == 0) {//
获取所有的数据条数
this.rows = PageDaoFactory.getPageDaoIntanse().getCount(counSql);
}
this.curr=curr;
this.size = size;//
设定页面显示数据大小
this.count = (int) Math.ceil((double) this.rows / this.size);
this.last=isLast();
}
/**
*
页面指令处理及返回相应的查询
SQL
语句
*/
public String pageDeal(String pageDo, String sql) {
String str = " limit ";
//
首页
if (pageDo.equals("first")) {
setCurr(1);
str += "" + getSize();
}
//
尾页
if (pageDo.equals("end")) {
setCurr(getCount());
str += "" + ((getCount() - 1) * getSize());
str += "," + (getRows() - (getCount() - 1) * getSize());
}
//
下一页
if (pageDo.equals("next")) {
if(getCurr()<getCount()){
str += "" + (getCurr() * getSize());
str += "," + getSize();
setCurr(getCurr() + 1);
}else{
setCurr(getCount());
str += "" + ((getCount() - 1) * getSize());
str += "," + (getRows() - (getCount() - 1) * getSize());
}
}
//
上一页
if (pageDo.equals("prv")) {
setCurr(getCurr() - 1);
str += "" + (getCurr() * getSize() - getSize());
str += "," + getSize();
}
return sql + str;
}
public static void main(String[] args) {
}
//
返回总页数,总页最小也等于
1
public int getCount() {
return (count == 0) ? 1 : count;
}
//
设置总页数
public void setCount(int count) {
this.count = count;
}
//
返回当前页
,
当前页最小也等于
1
public int getCurr() {
return (curr == 0) ? 1 : curr;
}
//
设置当前页
public void setCurr(int curr) {
this.curr = curr;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
/**
*
如果是最后一页的返回
true
* @return
*/
public boolean isLast() {
return (curr==count)?true:false;
}
public void setLast(boolean last) {
this.last = last;
}
}
这个类写了很多的注释,不过还是要讲解一下。由于在
Struts
的
Action
里用到第三个构造器,那就先讲这个吧。构造器里主要的功能是,通过
Factory
映射的接口类调用读取数据表的行数,获得表的所有行数。然后和传进来的页面显示信息数除一下,就获得页数的总数了。
当前页的定义,要是第一次读取,当前页当然是第一页了,要是点了下一页,当前页就加一页,点上一页,当前页就减一面,嘿嘿。我这里主要由页面传当前页进来,再根据传进来的动作进行处理当前页。所以“下一页”这样的动作除了要传一个动作外还要传当时的当前页。
Action
里通过调用
pageDeal
(“”,“”)这方法就就可以获取相应的分页处理了,当然还要加上
”select * from table”
这样的语句才能实现。
好了,看下一步
Action
里是怎样处理的。
第八步:
Action
的处理:
在
struts.action
的包里创建如下类:
package com.yourcompany.struts.action;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.yourcompany.dbtool.PageBean;
import com.yourcompany.factory.PageDaoFactory;
import com.yourcompany.vo.Product;
public class ProductShowAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
ArrayList aList = new ArrayList();
/*
*
定义页面传过来的动作,如点
"
下一页
"
并因为这动作而决定处理
*/
String pageDo = request.getParameter("pageDo");
/*
*
定义获取页面传过来的当前页
getCurr
*/
int getCurr;
String curr_page = request.getParameter("curr_page");
if (curr_page == null || curr_page.equals("")) {
getCurr = 1;
} else {
getCurr = Integer.parseInt(request.getParameter("curr_page"));
System.out.println(getCurr);
}
/*
*
实例化
PageBean
对象
* PageBean
有几个构造器,不过都要传送一句获取数据库行数的
SQL
语句
* getCurr
是传送一个当前页给
PageBean
的构造器,
* 2
是定义每页显示几行数据
*/
PageBean pb = new PageBean("select count(*) from product", getCurr,
2);
//
定义查询数据库的
SQL
语句,格式如下
String sql;
sql = pb.pageDeal(pageDo, "select * from product ");
//
定义
ArrayList
获取数据库所查询得到的数据
aList = PageDaoFactory.getPageDaoIntanse().getProduct(sql);
//
把值传给客户端
request.setAttribute("pageInfo", pb);
request.setAttribute("data", aList);
return mapping.findForward("success");
}
}
这个
Action
里也写了好多的注释,相信一看就明白。
步骤主要是:
1.
定义两个参数,获取前台传进来的动作和当前页
2.
实例化分页的处理类,
PageBean.java
。在它的构造器里传进查询数据库行数的
SQL
语句、当前页、要在表里显示的规格。
3.
获取处理好的分页
SQL
语句,主要是调用
PageBean
里的
pageDeal
方法。给它传进的是页面传进来的动作和查询数据表的
SQL
语句。
4.
用处理好的分布
SQL
语句去查询数据。
5.
把值传给前台。主要返回
PageBean
的对象和所查询得的数据
ArrayList
。
第九步:
前台处理页面。
由于后台传回来的是一个
ArrayList
的数据表,所以把它读出来就是。
还返回一个
PageBean
的对象,这里包含的数据是当前页、总页、是否为最后一页。
所以要是想弄不同的“上一页”、“下一页”这样的导航条的话,修改传回的参数,再在
Jsp
页面里做相应的处理就
OK
了。
看我的
Jsp
页面:
index.jsp
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<% if(session.getAttribute("getData")==null)
{//
这里只是一个跳转,没什么
session.setAttribute("getData","ok");
response.setHeader("refresh",
"1;url=/strutsPage/productShow.do?pageDo=first&curr_page=1");
}
%>
<html>
<head>
<title>JSP for ProductShowForm form</title>
</head>
<body><font color="#0000ff">
这里仅演示分页,操作部分已经做到获取
ID
了,相信直接调用就可以弄修改和删除
</font>
<table width="80%" border="1">
<tr>
<th>
商品名称
</th>
<th>
价格
</th>
<th>
商品描述
</th>
<th>
商品详细信息
</th>
<th >
上架日期
</th>
<th colspan="2" align="center">
操作
</th>
</tr>
<logic:present name="data" scope="request">
<logic:iterate id="show" name="data"
type="com.yourcompany.vo.Product">
<tr>
<td>
<bean:write name="show" property="name" />
</td>
<td>
<bean:write name="show" property="saleprice" />
</td>
<td>
<bean:write name="show" property="descript" />
</td>
<%--<td>
<bean:write name="show" property="contents" />
</td>
--%><td >
<bean:write name="show" property="saledate" />
</td>
<td>
<html:link action="/productShow.do?pageDo=updata"
paramId="up_page" paramName="show" paramProperty="id">
修改
</html:link>
</td>
<td>
<html:link action="/productShow.do?pageDo=dele"
paramId="dele_page" paramName="show" paramProperty="id">
删除
</html:link>
</td>
</tr>
</logic:iterate>
</logic:present>
</table>
<logic:present name="pageInfo">
第
<bean:write name="pageInfo" property="curr" />
页
/
共
<bean:write name="pageInfo" property="count" />
页
.
<html:link action="/productShow.do?pageDo=first"
paramId="curr_page" paramName="pageInfo" paramProperty="curr">
首页
</html:link>
<logic:notEqual name="pageInfo" property="curr" value="1">
<html:link action="/productShow.do?pageDo=prv"
paramId="curr_page" paramName="pageInfo" paramProperty="curr">
上一页
</html:link>
</logic:notEqual>
<logic:equal name="pageInfo" property="last" value="false">
<html:link action="/productShow.do?pageDo=next"
paramId="curr_page" paramName="pageInfo" paramProperty="curr">
下一页
</html:link>
</logic:equal>
<html:link action="/productShow.do?pageDo=end"
paramId="curr_page" paramName="pageInfo" paramProperty="curr">
尾页
</html:link>
</logic:present>
</body>
</html>
总结:
这个分页看起来很简单,做起来也很简单。只是对
SQL
语句做了一下过滤而已。这个分页功能很简单,但重在抛砖引玉!!
想要源代码的朋友和我联系。
作者:树下无影
2008-04-27
注:转载要经本人同意!