虽然现在有很多框架可以很简单的实现分页这个功能,但是我觉的对于初学者来说,还是很有必要学习自己手动实现分页这个功能,更好的理解分页的原理,编程最重要的就是思想.
1 思路分析
在写代码之前我们得分析怎样实现分页,把思路分析清楚了,写起代码来才能游刃有余.我们来看看分页的效果.
![image]
这就是我们要实现的效果从效果图中我们可以看到,要把数据按照我们希望的方式展示,我么能的到的数据有
totalPage 总页数
currentPage 当前页数
pageSize 每页显示的数据条数
totalSize 总的数据条数
还有就是每页显示的数据条数,是需要我们从后台时时传过来的,那我们可以把这些每页显示的数据封装到一个JavaBean中,然后把它存到域对象中,最后展示到前端页面.
如果上面的这些数据我们一个一个的从后台去取的话,操作起来太麻烦了,于是我们想,前台不就是需要这些数据吗?那我们可以把这些数据有封装到一个PageBean对象身上,到时候把它页存到域对象中,然后到jsp页面展示出来不就行了吗,对吧?
List<T> 用于存放每页要显示的数据的list
扫描二维码关注公众号,回复:
1031567 查看本文章
创建Product Bean用来封装从数据库中的到的数据
package bean;
import java.io.Serializable;
import java.util.Date;
public class Product implements Serializable{
private static final long serialVersionUID = 2078432725470146037L;
//商品pid
private String pid;
//商品名称
private String pname; //市场价格 private Double market_price; //商城价格 private Double shop_price; //商品图片 private String pimage; //商品上架时间 private String pdate; //商品描述 private String pdesc; public String getPid() { return pid; } public void setPid(String pid) { this.pid = pid; } public String getPname() { return pname; } public void setPname(String pname) { this.pname = pname; } public Double getMarket_price() { return market_price; } public void setMarket_price(Double market_price) { this.market_price = market_price; } public Double getShop_price() { return shop_price; } public void setShop_price(Double shop_price) { this.shop_price = shop_price; } public String getPimage() { return pimage; } public void setPimage(String pimage) { this.pimage = pimage; } public String getPdate() { return pdate; } public void setPdate(String pdate) { this.pdate = pdate; } public String getPdesc() { return pdesc; } public void setPdesc(String pdesc) { this.pdesc = pdesc; } public static long getSerialversionuid() { return serialVersionUID; } @Override public String toString() { return "Product [pid=" + pid + ", pname=" + pname + ", market_price=" + market_price + ", shop_price=" + shop_price + ", pimage=" + pimage + ", pdate=" + pdate + ", pdesc=" + pdesc + "]"; } }
创建PageBean用来封装前台页面需要的数据
package bean;
import java.io.Serializable;
import java.util.List;
public class PageBean implements Serializable{
private static final long serialVersionUID = 1L;
//当页要显示的商品集合
private List<Product> list;
//当前页数
private int currentPage; //每页显示数据条数 private int pageSize; //总页数 private int totalPage; //总条数 private Long totalSize; //每页要显示的数据 public List<Product> getList() { return list; } public void setList(List<Product> list) { this.list = list; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public Long getTotalSize() { return totalSize; } public void setTotalSize(Long totalSize) { this.totalSize = totalSize; } @Override public String toString() { return "PageBean [list=" + list + ", currentPage=" + currentPage + ", pageSize=" + pageSize + ", totalPage=" + totalPage + ", totalSize=" + totalSize + "]"; } }
在Dao层操作数据库,完成数据的封装
package dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.sun.org.apache.bcel.internal.generic.NEW;
import bean.Product;
import utils.C3P0Utils;
import utils.DBUtils;
import utils.TransctionManager;
public class ProductDao {
/**
* 每页显示的商品集合
*
* @param pageSize
* @param currentPage
* @throws SQLException */ public List<Product> pageProduct(int currentPage, int pageSize) throws SQLException { int a = (currentPage - 1) * pageSize; QueryRunner runner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "select * from product limit ?,?"; List<Product> list = runner.query(sql, new BeanListHandler<>(Product.class),a,pageSize); return list; } /** * 查询总记录数 */ public Long queryProductCount() throws SQLException { QueryRunner runner = new QueryRunner(C3P0Utils.getDataSource()); String sql = "select count(*) from product"; Long count = (Long) runner.query(sql, new ScalarHandler()); return count; } }
在Service层完成业务逻辑
package service;
import java.sql.SQLException;
import java.util.List;
import bean.PageBean;
import bean.Product;
import dao.ProductDao;
import utils.TransctionManager;
public class ProductService {
/**
* 分页查询所有商品
*/
public PageBean pageQuery(int currentPage) {
// 封装PageBean /** * 分别获取到: 当前页 每页显示数据条数 每页要显示的商品集合 总页数 总数据条数 */ PageBean bean = new PageBean(); // 当前页 bean.setCurrentPage(currentPage); // 每页显示数据条数 int pageSize = 5; bean.setPageSize(pageSize); // 每页要显示的商品集合 ProductDao dao = new ProductDao(); try { List<Product> products = dao.pageProduct(currentPage, pageSize); bean.setList(products); // 总数据条数 Long totalSize = dao.queryProductCount(); bean.setTotalSize(totalSize); // 总页数 int totalPage = 0; totalPage = (int) (totalSize / pageSize); if (totalSize % pageSize != 0) { totalPage++; } bean.setTotalPage(totalPage); } catch (SQLException e) { e.printStackTrace(); } return bean; } }
在Servlet中编写控制代码
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.BeanUtils;
import bean.PageBean;
import bean.Product;
import service.ProductService;
import utils.DateUtil;
/**
* 用来处理分页的Servlet,利用反射技术实现动态获取前台调用的方法,这里使用反射技术是为了增 强代码的可维护性.
如果不使用反射技术,那么我们要么只能时针对前台的每个请求我们都写一个Servlet,或者使用if{}else if 来判断前台传过来的方法名
*/
public class BigServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 解决中文乱码问题 request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); String methods = request.getParameter("method"); //通过反射技术获取servlet字节码文件对象,创建对象然后调用方法,注意:一个servlet只有只有一个对象 Class<? extends BigServlet> clazz = this.getClass(); try { Method method = clazz.getMethod(methods, HttpServletRequest.class,HttpServletResponse.class); method.invoke(this,request,response); } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } /** * 分页查询 */ public void page(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { //获取请求参数 int currentPage = Integer.parseInt(request.getParameter("currentPage")); //调用业务层的方法获取pageBean ProductService service=new ProductService(); PageBean bean=service.pageQuery(currentPage); //把数据存入域对象中 HttpSession session = request.getSession(); session.setAttribute("page",bean); response.sendRedirect(request.getContextPath()+"/page.jsp"); } }
C3P0连接池工具类
package utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils {
/**
* c3p0连接池工具类
*/
private static ComboPooledDataSource dataSource;
static {
dataSource=new ComboPooledDataSource(); } public static DataSource getDataSource() { return dataSource; } public static Connection getConnection() { Connection con=null; try { con= dataSource.getConnection(); } catch (SQLException e) { System.out.println(e); throw new RuntimeException("数据库链接异常,请联系技术人员"); } return con; } public static void close(ResultSet resultSet,PreparedStatement ps,Connection con) { if (resultSet!=null) { try { resultSet.close(); } catch (Exception e) { System.out.println(e); } } if (ps!=null) { try { ps.close(); } catch (Exception e) { System.out.println(e); } } if (con!=null) { try { con.close(); } catch (Exception e) { System.out.println(e); } } } }
用于封装数据的工具类(这个可以用commons-dbutils-1.4.jar代替),这个工具类可以自己封装,新手建议自己封装一下
package utils;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.management.RuntimeErrorException;
import javax.sql.DataSource;
public class DBUtils {
/**
* 操作数据库的工具类
*/
private DataSource dataSource;
public DBUtils(DataSource dataSource) {
this.dataSource = dataSource; } // 增删改方法 public int update(String sql, Object[] params) { PreparedStatement ps = null; int num = 0; // 注册驱动,获得链接 Connection con = C3P0Utils.getConnection(); // 获取执行对象 try { ps = con.prepareStatement(sql); // 设置?处参数 if (params != null) { for (int i = 1; i <= params.length; i++) { ps.setObject(i, params[i - 1]); } } num = ps.executeUpdate(); } catch (SQLException e) { System.out.println(e); throw new RuntimeException("数据库链接异常,请联系技术人员"); } // 关闭资源 C3P0Utils.close(null, ps, con); return num; } // 操作数据实现查询多条数据功能 public <E> List<E> query(String sql, Object[] params, Class<E> clazz) { PreparedStatement ps = null; List<E> list = null; ResultSet set = null; // 1注册驱动,获取链接 Connection con = C3P0Utils.getConnection(); try { // 2后去执行对象 ps = con.prepareStatement(sql); // 设置?处参数 if (params != null) { for (int i = 1; i <= params.length; i++) { ps.setObject(i, params[i - 1]); } } // 利用ps动态获取所有字段名 ResultSetMetaData metaData = ps.getMetaData(); // 利用字节码文件对象获取clazz对象中所有的方法 Method[] methods = clazz.getMethods(); // 3执行sql语句,处理结果集 set = ps.executeQuery(); // 遍历结果集,并把结果集封装到对象中,再把每对象封装到集合中 // 创建一个集合用于封装每个对象 list = new ArrayList<>(); while (set.next()) { // 创建对象用于封装每条数据 E e = clazz.newInstance(); // 遍历metaData获取每一个字段名 for (int i = 1; i <= metaData.getColumnCount(); i++) { String columnName = metaData.getColumnName(i); // 根据列明,获取每一列数据 Object object = set.getObject(columnName); // 遍历所有方法,找出setxx()的方法 for (Method method : methods) { String name = method.getName(); if (name.equalsIgnoreCase("set" + columnName)) { method.invoke(e, object); } } } list.add(e); } } catch (Exception e) { System.out.println(e); throw new RuntimeException("数据库链接异常,请联系技术人员"); } // 关闭资源 C3P0Utils.close(set, ps, con); return list; } // 操作数据实现查询一条数据 public <E> E queryBean(String sql, Object[] params, Class clazz) { PreparedStatement ps = null; ResultSet resultSet = null; E e = null; // 1注册驱动,获得链接