通用分页就是把我们经常使用的分页方法进行封装,然后用泛型传递对象,利用反射获取对象的所有属性并且赋值。
一般在实际项目的开发过程中我们会有很多数据的展示,并且数据量大,展示的数据种类繁多,这意味着我们要写很多重复的代码,我们可将重复相同的代码提取出来进行封装,后期进行调用即可。
1、明确我们的需求是什么?
2、在实际项目开发中分页需要哪些参数?页码(每页所展示的数据)、总记录数、是否分页、点击下一页或者上一页所需地址
PageBean 分页三要素 page 页码 视图层传递过来 rows 页大小 视图层传递过来 total 总记录数 后台查出来 pagination 是否分页 视图层传递过来 getStartIndex() 基于MySql数据库分页,获取分页开始标记
4.1.以书籍为例,创建一个书籍表,同时再创建一个书籍项目
- create table t_book(
- book_id int not null primary key auto_increment comment '书本编号',
- book_name varchar(30) not null comment '书本名称',
- book_name_pinyin varchar(30) null comment '书本拼音',
- book_price float default 0 comment '书本价格',
- book_type varchar(10) not null comment '书本类型'
- )comment '书本信息表';
-
-
- #分页(limit)
- #limit 参数1,参数2 (page-1)*rows
- #参数1:从第几条数据开始
- #参数2:每次返回多少条数据 rows
- #第一页:从0开始,返回2条
- #第二页:从2开始,返回2条
4.2.项目中的相关配置以及导入必要的依赖


依赖:
mysql-connector-java-5.1.44-bin.jar MySQL的驱动类
pinyin4j-2.5.0.jar 拼音的jar,作用是可以快速的将中文转变成英文,只提取拼音首字母
standard-1.1.2.jar jstl标签
jstl-1.2.jar
工具类:
CommonUtils.java 反射封装ResultSet结果集
DBHelper.java 连接数据库
config.properties 资源文件
EncodingFiter.java 中文乱码过滤器
StringUtils.java 判断字符串是否存在(为空)
PageTag.java 自定义标签的助手类
PageBean.java 分页工具类PinYinUtil.java 拼音工具类
4.3.先写一个分页工具类,用于实现分页效果。
- package com.zking.pagination.util;
-
- import java.io.Serializable;
- import java.util.Map;
-
- import javax.servlet.http.HttpServletRequest;
-
- /**
- * 分页工具类
- * @author gss
- *
- */
- public class PageBean implements Serializable{
- //当前页码,默认1
- private int page=1;
- //页面显示条数,默认10
- private int rows=10;
- //总记录数,默认0
- private int total=0;
- //是否分页标记,默认分页
- private boolean pageination=true;
-
- //http://localhost:8080/pagination/BookServlet.action
- ///pagination/BookServlet.action
- //获取上一次请求路径
- private String url;
-
- //获取上一次请求的请求参数集合
- // Map
params=req.getParameterMap(); - //
- private Map<String,String[]> params;
-
- public PageBean() {
- super();
- }
-
- /**
- * 获取起始记录的下标(基于Mysql分页,计算limit分页开始位置)
- * @return
- */
- public int getStartIndex() {
- return (this.page-1)*this.rows;
- }
-
- public void setRequest(HttpServletRequest req) {
- //获取前端提交的请求参数(分页三要素:页码、页大小、总记录数 )
- String page = req.getParameter("page");
- String rows = req.getParameter("rows");
- String pagination = req.getParameter("pagination");
-
- //赋值
- this.setPage(page);
- this.setRows(rows);
- this.setPageination(pagination);
-
- //获取上一次请求的请求路径
- //http://localhost:8080/pagination/BookServlet.action
- // req.getRequestURI()==等同于/pagination/BookServlet.action
- // req.getContextPath()==项目名/pagination
- // req.getServletPath()==请求路径/BookServlet.action
- //当前路径
- this.url = req.getRequestURI();
- //获取上一次请求的请求参数集合
- //Map
-->params.put("bookname",new String[]{"",""}) - this.params = req.getParameterMap();
- }
- /**
- * 获取最大页码
- * @return
- */
- public int getMaxPager() {
- int p = this.total/this.rows;
- //判断是否有余数,如果有余数,则最大页码+1
- if(this.total%this.rows!=0)
- p++;
- return p;
- }
- /**
- * 获取上一页
- * @return
- */
- public int getProviousPager() {
- int p = this.page-1;
- if(p<1)
- p=1;
- return p;
- }
- /**
- * 获取下一页
- * @return
- */
- public int getNextPager() {
- int p = this.page+1;
- if(this.page>=this.getMaxPager())
- p=this.getMaxPager();
- return p;
- }
-
- public void setPage(String page) {
- if(null!=page)
- this.page = Integer.parseInt(page);
- }
- public void setRows(String rows) {
- if(null!=rows)
- this.rows = Integer.parseInt(rows);
- }
- public void setPageination(String pageination) {
- if(null!=pageination)
- this.pageination = Boolean.parseBoolean(pageination);
- }
-
-
- public int getPage() {
- return page;
- }
-
- public void setPage(int page) {
- this.page = page;
- }
-
- public int getRows() {
- return rows;
- }
-
- public void setRows(int rows) {
- this.rows = rows;
- }
-
- public int getTotal() {
- return total;
- }
-
- public void setTotal(int total) {
- this.total = total;
- }
-
- public boolean isPageination() {
- return pageination;
- }
-
- public void setPageination(boolean pageination) {
- this.pageination = pageination;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public Map<String, String[]> getParams() {
- return params;
- }
-
- public void setParams(Map<String, String[]> params) {
- this.params = params;
- }
-
- @Override
- public String toString() {
- return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pageination=" + pageination
- + ", url=" + url + ", params=" + params + "]";
- }
-
- }
BaseDao.java(是一个通用的父类方法,来帮助我们实现通用的分类)
- package com.zking.pagination.dao;
-
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.List;
- import com.zking.pagination.util.DBHelper;
- import com.zking.pagination.util.PageBean;
-
- public class BaseDao
{ - public static interface CallBack
{ - //只用于遍历ResultSet结果集
- public List
foreachRs(ResultSet rs) throws SQLException; - }
-
- /**
- * 通用分页方法(既支持分页,也支持不分页)
- * @param sql 普通的sql
- * @param pageBean pageBean 分页对象
- * @return 查询结果集
- */
- public List
excuteQuery(String sql,PageBean pageBean,CallBack callBack) { - //声明对象
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- try {
- //获取连接对象
- conn = DBHelper.getConnection();
- //根据pageBean分页对象判断是否分页
- if(null!=pageBean&&pageBean.isPageination()) {
- //1.分页
- //1)根据满足条件查询总记录数
- String countSQL = this.getCountSQL(sql);
- //创建执行对象
- stmt = conn.prepareStatement(countSQL);
- //执行sql语句并返回总记录数
- rs = stmt.executeQuery();
- //获取总记录数
- if(rs.next()) {
- pageBean.setTotal(rs.getInt(1));
- }
- //2)根据满足条件查询分页结果集
- sql = this.getPagerSQL(sql, pageBean);//覆盖
- }
- //创建执行对象
- stmt = conn.prepareStatement(sql);
- //查询结果集
- rs = stmt.executeQuery();
-
- return callBack.foreachRs(rs);
- } catch (Exception e) {
- e.printStackTrace();
- }finally {
- DBHelper.close(conn, stmt, rs);
- }
- return null;
- }
-
- /**
- * 将普通的sql语句转换成查询总记录条数的sql语句
- * select * from t_book
- * select * from t_book where ...
- * select book_id,book_name from t_book
- * select book_id,book_name from t_book where ...
- * ------------>
- * select count(0) from t_book where ...
- * @param sql 普通的sql
- * @return 查询总记录数的sql
- */
- private String getCountSQL(String sql) {
- return "select count(0) from ("+sql+") temp";
- }
-
- /**
- * 将普通的sql语句转换成查询分页结果集的sql语句
- * select * from t_book
- * select * from t_book where ...
- * select book_id,book_name from t_book
- * select book_id,book_name from t_book where ...
- * ------------>
- * select * from t_book limit
- * select * from t_book where 1=1 limit
- * @param sql 普通的sql
- * @param pageBean 分页对象(包含当前页码和每页条数,用于计算分页的关键数据)
- * @return 查询分页结果集的sql
- */
- private String getPagerSQL(String sql,PageBean pageBean) {
- return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();
- }
-
- }
BookDao.java(dao类继承了BaseDao 父类,代码简洁,通用的方法都在父类中)
- package com.zking.pagination.dao;
-
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
- import javax.management.RuntimeErrorException;
- import com.zking.pagination.entity.Book;
- import com.zking.pagination.util.DBHelper;
- import com.zking.pagination.util.PageBean;
- import com.zking.pagination.util.StringUtils;
-
- public class BookDao extends BaseDao
{ - //1、书本新增
- public void addBook(Book book) {
- //声明对象
- Connection conn = null;
- PreparedStatement stmt = null;
- try {
- //获取连接对象
- conn= DBHelper.getConnection();
- //定义sql语句
- String sql = "insert into t_book(book_name,book_name_pinyin,book_price,book_type) values(?,?,?,?)";
- //创建执行对象
- stmt = conn.prepareStatement(sql);
- //参数赋值
- stmt.setString(1, book.getBook_name());
- stmt.setString(2, book.getBook_name_pinyin());
- stmt.setFloat(3, book.getBook_price());
- stmt.setString(4, book.getBook_type());
- //执行sql语句并返回影响行数
- int i = stmt.executeUpdate();
- if(i<1) {
- throw new RuntimeException("影响行数为0,添加失败");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally {
- DBHelper.close(conn, stmt, null);
- }
- }
-
- /**
- * 2、书本分页查询 query/find/select/get
- * @param book 要查询的对象
- * @return 返回结果集
- */
- public List
queryBookPager(Book book,PageBean pageBean){ - //定义sql语句
- String sql = "select book_id,book_name,book_name_pinyin,book_price,book_type from t_book where 1=1";
- //拼接查询条件,按照书本名称模糊查询
- if(StringUtils.isNotBlank(book.getBook_name()))
- sql+=" and book_name like '%"+book.getBook_name()+"%'";
- //按照书本编号降序排序
- sql+=" order by book_id desc";
- System.out.println(sql);
-
- return super.excuteQuery(sql, pageBean, new CallBack
() { -
- @Override
- public List
foreachRs(ResultSet rs) throws SQLException { - List
blist = new ArrayList<>(); - //定义Book对象
- Book b = null;
- //循环遍历结果集
- while(rs.next()) {
- //创建Book对象
- b = new Book();
- b.setBook_id(rs.getInt("book_id"));
- b.setBook_name(rs.getString("book_name"));
- b.setBook_name_pinyin(rs.getString("book_name_pinyin"));
- b.setBook_price(rs.getFloat("book_price"));
- b.setBook_type(rs.getString("book_type"));
- //将对象添加到集合中
- blist.add(b);
- }
- return blist;
- }
- });
-
- //以下为查询原生态代码
- /* List
blist = new ArrayList<>(); - Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- try {
- //获取连接对象
- conn= DBHelper.getConnection();
- //定义sql语句
- String sql = "select book_id,book_name,book_name_pinyin,book_price,book_type from t_book where 1=1";
- //拼接查询条件,按照书本名称模糊查询
- if(StringUtils.isNotBlank(book.getBook_name()))
- sql+=" and book_name like '%"+book.getBook_name()+"%'";
- //按照书本编号降序排序
- sql+=" order by book_id desc";
- System.out.println(sql);
- //创建执行对象
- stmt = conn.prepareStatement(sql);
- //执行sql语句并返回查询结果集
- rs = stmt.executeQuery();
- //定义Book对象
- Book b = null;
- //循环遍历结果集
- while(rs.next()) {
- //创建Book对象
- b = new Book();
- b.setBook_id(rs.getInt("book_id"));
- b.setBook_name(rs.getString("book_name"));
- b.setBook_name_pinyin(rs.getString("book_name_pinyin"));
- b.setBook_price(rs.getFloat("book_price"));
- b.setBook_type(rs.getString("book_type"));
- //将对象添加到集合中
- blist.add(b);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally {
- DBHelper.close(conn, stmt, rs);
- }
- return blist;*/
- }
- }
BookDaoTest.java 使用Junit测试
- package com.zking.pagination.dao;
-
- import static org.junit.Assert.*;
- import java.util.List;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- import com.zking.pagination.entity.Book;
- import com.zking.pagination.util.PageBean;
- import com.zking.pagination.util.PinYinUtil;
-
- public class BookDaoTest {
- Book book = null;
- BookDao bd = new BookDao();
-
- @Before
- public void setUp() throws Exception {
- //初始化一次
- book = new Book();
- //System.out.println("setUp");
- }
-
- @After
- public void tearDown() throws Exception {
- //System.out.println("tearDown");
- }
-
- @Test
- public void testAddBook() {
- for (int i = 0; i < 64; i++) {
- book = new Book();
- book.setBook_name("红楼梦第"+(i+1)+"章");
- book.setBook_name_pinyin(PinYinUtil.toPinyin("红楼梦第"+(i+1)+"章").toLowerCase());
- book.setBook_price(128f);
- book.setBook_type("文学");
- //调用dao类添加方法
- bd.addBook(book);
- }
- //System.out.println("testAddBook");
- }
-
- @Test
- public void testQueryBookPager() {
- //模糊查询
- book.setBook_name("2");
- PageBean pageBean = new PageBean();
- pageBean.setPage(2);//第二页
- pageBean.setRows(8);//每页条数
- //pageBean.setPageination(false);//不分页
- //调用dao类查询方法
- List
books = bd.queryBookPager(book,pageBean); - System.out.println("总记录数:"+pageBean.getTotal());
- books.forEach(System.out::println);
- }
- }

BookServlet.java
- package com.zking.pagination.action;
-
- import java.io.IOException;
- import java.util.List;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import com.zking.pagination.dao.BookDao;
- import com.zking.pagination.entity.Book;
- import com.zking.pagination.util.PageBean;
-
- public class BookServlet extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- this.doPost(req, resp);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //获取请求查询参数
- String bookname = req.getParameter("bookname");
- //实例化BookDao
- BookDao bd = new BookDao();
- //实例化Book
- Book book = new Book();
- book.setBook_name(bookname);
- //创建PageBean
- PageBean pageBean = new PageBean();
- //必须在查询之前完成请求参数赋值
- pageBean.setRequest(req);
- //实现书本查询
- List
books = bd.queryBookPager(book,pageBean); - //将查询的结果books保存到request作用域中
- req.setAttribute("books", books);
- //将pageBean对象存入到request作用域中
- req.setAttribute("pageBean", pageBean);
- //转发到指定页面并显示查询结果
- req.getRequestDispatcher("/bookList.jsp").forward(req, resp);;
- }
-
- }
配置web.xml
- <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
- <display-name>paginationdisplay-name>
-
-
- <filter>
- <filter-name>encodingFilterfilter-name>
- <filter-class>com.zking.pagination.util.EncodingFilterfilter-class>
- filter>
- <filter-mapping>
- <filter-name>encodingFilterfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
-
-
- <servlet>
- <servlet-name>BookServletservlet-name>
- <servlet-class>com.zking.pagination.action.BookServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>BookServletservlet-name>
- <url-pattern>/BookServlet.actionurl-pattern>
- servlet-mapping>
-
- web-app>
z标签:是我们的分页标签它还有一个主要的类-----PaginationTag助手类,是整个分页的灵魂所在。
- package com.zking.pagination.tag;
-
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Set;
- import javax.servlet.jsp.JspException;
- import javax.servlet.jsp.JspWriter;
- import javax.servlet.jsp.tagext.BodyTagSupport;
- import com.zking.pagination.util.PageBean;
-
- public class PaginationTag extends BodyTagSupport {
-
- private PageBean pageBean;
-
- @Override
- public int doEndTag() throws JspException {
- return EVAL_PAGE;
- }
-
- @Override
- public int doStartTag() throws JspException {
- JspWriter out = pageContext.getOut();
- try {
- out.write(toHtml());
- } catch (Exception e) {
- e.printStackTrace();
- }
- return SKIP_BODY;
- }
-
- private String toHtml() {
- //判断是否分页
- if(null==pageBean||!pageBean.isPageination())
- return "";
- else {
- StringBuilder sb=new StringBuilder();
- //TODO
- sb.append("");
-
- //拼接Form表单
- sb.append("
-
- //设置page隐藏域
- sb.append("");
-
- //拼接请求参数集合
- Map
map = pageBean.getParams(); - //获取请求参数集合键值对
- Set
> entrySet = map.entrySet(); - //遍历请求参数键值对
- for (Entry
entry : entrySet) { - //获取请求参数名,也就是来自于表单中的name属性名称
- String name=entry.getKey();
- //如果参数为page,则continue跳过
- if(name.equals("page"))
- continue;
- //获取请求参数对应的值,String[]
- String[] values=entry.getValue();
- //遍历value值
- for (String value : values) {
- //拼接请求参数
- sb.append("");
- }
- }
-
- sb.append("");
-
- //拼接共几页/第几页
- sb.append("[第"+pageBean.getPage()+"页/共"+pageBean.getMaxPager()+"页]");
-
- //拼接首页、上一页、下一页、末页
- if(pageBean.getPage()==1)
- sb.append("首页 上一页 ");
- else {
- sb.append("首页 ");
- sb.append("+pageBean.getProviousPager()+")\">上一页 ");
- }
- if(pageBean.getPage()==pageBean.getMaxPager())
- sb.append("下一页 末页 ");
- else {
- sb.append("+pageBean.getNextPager()+")\">下一页 ");
- sb.append("+pageBean.getMaxPager()+")\">末页 ");
- }
-
- //拼接跳转页码
- sb.append("");
- sb.append("");
-
- //拼接javascript跳转方法
- sb.append("");
-
- sb.append("");
- return sb.toString();
- }
- }
-
- public PageBean getPageBean() {
- return pageBean;
- }
-
- public void setPageBean(PageBean pageBean) {
- this.pageBean = pageBean;
- }
-
- }
启动Tomcat
bookList.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
- <%@taglib uri="/zking" prefix="z" %>
- 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=UTF-8">
- <title>Insert title heretitle>
- head>
- <body>
- <form action="BookServlet.action" method="post" align="center">
- <label>书本名称:label><input type="text" name="bookname"/>
- <input type="submit" value="查询"/>
- form>
-
- <table width="100%" border="1" cellpadding="0" cellspacing="0">
- <tr>
- <th>书本编号th>
- <th>书本名称th>
- <th>书本拼音th>
- <th>书本价格th>
- <th>书本类型th>
- tr>
- <c:forEach items="${books }" var="b">
- <tr>
- <th>${b.book_id }th>
- <th>${b.book_name }th>
- <th>${b.book_name_pinyin }th>
- <th>${b.book_price }th>
- <th>${b.book_type }th>
- tr>
- c:forEach>
- table>
- <z:pagination pageBean="${pageBean }"/>
- <%-- <div style="float: right;">
- <form id="ff" action="${pageBean.getUrl()}" method="post">
- <input type="hidden" name="page"/>
-
- Map
maps = ${pageBean.getParams() } -
- <input type="hidden" name="bookname" value="1"/>
- form>
- [第${pageBean.getPage()}页/共${pageBean.getMaxPager()}页]
- <a href="javascript:gotoPage(1);">首页a>
- <a href="javascript:gotoPage(${pageBean.getProviousPager()});">上一页a>
- <a href="javascript:gotoPage(${pageBean.getNextPager()});">下一页a>
- <a href="javascript:gotoPage(${pageBean.getMaxPager()});">末页a>
- <input type="text" id="go" style="width:18px"/>
- <input type="button" value="GO" onclick="skipPage(${pageBean.getMaxPager()})" />
- div> --%>
- body>
- html>
效果图:

