通用分页超详细介绍(附带源代码解析&页面展示效果)

avatar
作者
筋斗云
阅读量:0

1.BookDao实现及测试

创建BookDao并定义实现书本查全部方法,最后完成Junit方法测试。

public class BookDao extends BaseDao<Book>{     /**      * 添加      * @param book      */     public void addBook(Book book){         Connection con = null;         PreparedStatement ps = null;         try{             //获取连接对象             con=DBHelper.getConnection();             ps=con.prepareStatement("insert into t_book values(?,?,?,?)");             ps.setString(1,book.getBookid());             ps.setString(2,book.getBookname());             ps.setFloat(3,book.getPrice());             ps.setString(4,book.getBooktype());             //执行SQL语句并返回影响行数             int i=ps.executeUpdate();             if(i<0)                 throw new Exception("执行失败,影响函数为0");         }catch (Exception e){             e.printStackTrace();         }finally {             DBHelper.close(con,ps,null);         }     }      /**      * 模糊查询      * @param book      * @return      */     public List<Book> getByLike(Book book, PageBean pageBean) {         String sql = "select * from t_book where 1=1";         if (StringUtils.isNotBlank(book.getBookname()))             sql += " and bookname like '%" + book.getBookname() + "%'";         System.out.println(sql);         return super.executeQuery(sql, pageBean, new CallBack<Book>() {             @Override             public List<Book> foreachRs(ResultSet rs) throws SQLException {               return CommonUtils.toList(rs,Book.class);             }         });     } }

2.BookServlet实现及页面效果展示

创建BookServlet并调用BookDao中查全部方法实现书本查询。

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");         //创建Book对象         Book book=new Book();         book.setBookname(bookname);         //调用模糊查询方法         PageBean pageBean=new PageBean();         BookDao bookDao=new BookDao();         //获取前端传入的请求参数集         pageBean.setRequest(req);         List<Book> books = bookDao.getByLike(book,pageBean);         //将查询结果保存到request作用域中         req.setAttribute("books",books);         //将pageBean保存到request作用域中         req.setAttribute("pageBean",pageBean);         //转发         req.getRequestDispatcher("index.jsp").forward(req,resp);     } } 

1)打开web.xml,配置中文乱码过滤器EncodingFilter和书本查询Servlet控制器;

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"          version="4.0">     <!--1、配置中文过滤器-->     <filter>         <filter-name>encodingFilter</filter-name>         <filter-class>com.zking.pagintation.uitl.EncodingFilter</filter-class>     </filter>     <filter-mapping>         <filter-name>encodingFilter</filter-name>         <url-pattern>/*</url-pattern>     </filter-mapping>     <!--2、配置Servlet的servlet-->     <servlet>         <servlet-name>Servlet</servlet-name>         <servlet-class>com.zking.pagintation.servlet.BookServlet</servlet-class>     </servlet>     <servlet-mapping>         <servlet-name>Servlet</servlet-name>         <url-pattern>/Servlet.do</url-pattern>     </servlet-mapping>     <!--3、配置欢迎页-->     <welcome-file-list>         <welcome-file>/index.jsp</welcome-file>     </welcome-file-list> </web-app>

2)创建BookServlet.jsp页面实现书本查询效果展示。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="z" uri="/zking" %> <html> <head>     <title>通用分页</title> </head> <body> <h1>通用分页</h1> <form method="post" action="Servlet.do">     <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>     </tr>     <c:forEach var="b" items="${books}">         <tr>             <td>${b.bookid}</td>             <td>${b.bookname}</td>             <td>${b.price}</td>             <td>${b.booktype}</td>         </tr>     </c:forEach> </table> <z:pagination pageBean="${pageBean}"/> </body> </html> 

3.通用分页实现

3.1.MySQL分页

  • limit语法

select * from table_name limit [offset,] rows
  • 参数说明

参数说明
offset指定第一个返回记录行的偏移量(即从哪一行开始返回),注意:初始行的偏移量为0
rows返回具体行数

3.2.PageBean

创建PageBean分页标记类,用于定义分页相关要素。

/**  * 分页工具类  */ public class PageBean {     //当前页码     private int page=1;     //每页条数     private int rows=10;     //总机录数     private int total=0;     //是否分页标记     private boolean pagination=true;      //增强属性     //返回上一条请求的url路径     private String url;     //获取上一次请求的所有请求参数集合     private Map<String,String[]> maps;      public void setRequest(HttpServletRequest req){         //1、获取前端传入的分页三要素(page,rows,pagination)         String page = req.getParameter("page");         String rows = req.getParameter("rows");         String pagination = req.getParameter("pagination");          this.setPage(page);         this.setRows(rows);         this.setPagination(pagination);         //2、获取上一次请求的URL路径         //req.getContextPath == 获取项目名         //req.getServletPath() == 获取servlet请求路径名         //req.getRequestURL == req.getContextPath+req.getServletPath()         this.url=req.getRequestURI();         //3、获取上一次请求的所有请求参数集合          this.maps = req.getParameterMap();     }        /**      * 返回limit分页查询的开始位置      * @return      */     public int getStartIndex(){         return (this.page-1)*this.rows;     }      //重载set方法     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 setPagination(String pagination) {         if(null!=pagination)             this.pagination = Boolean.parseBoolean(pagination);     }      /**      * //分页方法      * //计算总分页      * @return 总分页数      */     public int getMaxPager(){         int max = this.total/this.rows;         //除不尽有余数         if(this.total%this.rows!=0)             max++;             return max;     }      /**      * 上一页方法      * @return 上一页页数      */     public int getPrevPager(){         int prev = this.page-1;         if(prev<=1)             prev=1;         return prev;     }      /**      * 下一页方法      * @return 下一页页数      */     public int getNextPager(){         int next=this.page+1;         if(next>=getMaxPager())             next=getMaxPager();         return next;     }      public String getUrl() {         return url;     }      public void setUrl(String url) {         this.url = url;     }      public Map<String, String[]> getMaps() {         return maps;     }      public void setMaps(Map<String, String[]> maps) {         this.maps = maps;     }      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 isPagination() {         return pagination;     }      public void setPagination(boolean pagination) {         this.pagination = pagination;     }      @Override     public String toString() {         return "PageBean{" +                 "page=" + page +                 ", rows=" + rows +                 ", total=" + total +                 ", pagination=" + pagination +                 ", url='" + url + '\'' +                 ", maps=" + maps +                 '}';     } }

3.3.BaseDao

创建BaseDao通用分页类并定义相关分页方法。

3.3.1分页查询方法

public class BaseDao<T> { /**      * 通用分页方法 (分页或不分页)      * @param sql 普通SQL语句      * @param pageBean 分页标记对象      * @return 返回分页结果集      */     public List<T> executeQuery(String sql, PageBean pageBean,CallBack<T> callBack){         Connection con=null;         PreparedStatement ps=null;         ResultSet rs=null;         try{             con= DBHelper.getConnection();             if(null!=pageBean&&pageBean.isPagination()){                 //分页                 //1)根据满足的条件查询分页总记录数                 String countSQL = this.getCountSQL(sql);                 ps=con.prepareStatement(countSQL);                 rs=ps.executeQuery();                 if(rs.next()){                     int total = rs.getInt(1);                     //将查询得到的总记录数存入Page Bean对象中的total属性                     pageBean.setTotal(total);                 }                 //2)根据满足的条件查询分页结果集                 sql = this.getPagerSQL(sql, pageBean);             }                 ps=con.prepareStatement(sql);                 rs=ps.executeQuery();                 return callBack.foreachRs(rs);         }catch (Exception e){             e.printStackTrace();         }finally {             DBHelper.close(con,ps,rs);         }         return null;     } }

在executeQuery方法中根据PageBean对象及对象属性pagination识别是否分页。

  • 分页:查询分页结果、集查询总记录数

  • 将普通的SQL语句转换成分页查询的SQL语句

/**      * 将普通的SQL语句转换成分页查询的SQL语句      * @param sql 普通SQL语句      * @param pageBean 分页标记对象      * @return 分页查询的SQL语句      */     private String getPagerSQL(String sql,PageBean pageBean){         return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();     }
  •  将普通sql语句转换成查总记录数的sql
    /**      * 将普通sql语句转换成查总记录数的sql      * @param sql      * @return 查询总记录数的SQL语句      */     private String getCountSQL(String sql){         return "select count(*) from ("+sql+") temp";     }
 
  • 不分页:只查询数据结果集(不查询分页记录和总记录数)

3.3.2.匿名内部接口

在BaseDao类中定义匿名内部接口,该接口中的forEach方法只用于循环遍历ResultSet查询结果集并返回List<T>

/** * 用于遍历结果集数据的回调接口 * @author Administrator * @param <T> */  public static interface CallBack<T>{         public List<T> foreachRs(ResultSet rs) throws SQLException;     }

修改executeQuery方法,将匿名内部接口CallBack当做入参传入方法中。

public List<T> executeQuery(String sql, PageBean pageBean,CallBack<T> callBack){         Connection con=null;         PreparedStatement ps=null;         ResultSet rs=null;         try{             con= DBHelper.getConnection();             if(null!=pageBean&&pageBean.isPagination()){                 //分页                 //1)根据满足的条件查询分页总记录数                 String countSQL = this.getCountSQL(sql);                 ps=con.prepareStatement(countSQL);                 rs=ps.executeQuery();                 if(rs.next()){                     int total = rs.getInt(1);                     //将查询得到的总记录数存入Page Bean对象中的total属性                     pageBean.setTotal(total);                 }                 //2)根据满足的条件查询分页结果集                 sql = this.getPagerSQL(sql, pageBean);             }                 ps=con.prepareStatement(sql);                 rs=ps.executeQuery();                 return callBack.foreachRs(rs);         }catch (Exception e){             e.printStackTrace();         }finally {             DBHelper.close(con,ps,rs);         }         return null;     }

3.3.3.Junit单元测试

Junit是一个Java测试框架,使编写可靠和高效的测试变得容易。它可以用于大多数语言制作的应用程序,但特别适合于测试Java应用程序。Junit也可以用来创建自动测试。

Junit框架是最流行的Java测试框架之一。它提供了一些功能,使编写测试变得容易,包括支持多个测试用例、断言和报告。Junit也是多功能的,允许用各种语言编写测试。

setUp():在方法之前执行

tearDown:在方法之后执行

public class BookDaoTest { ​     @Before     public void setUp() throws Exception {     } ​     @After     public void tearDown() throws Exception {     } ​     @Test     public void testQueryBookPager() {         fail("Not yet implemented");     } ​ }

Junit中的setUp和tearDown方法是根据方法数量来决定的

4.增强PageBean

package com.zking.pagintation.uitl;  import javax.servlet.http.HttpServletRequest; import java.util.Map;  /**  * 分页工具类  */ public class PageBean {     //当前页码     private int page=1;     //每页条数     private int rows=10;     //总机录数     private int total=0;     //是否分页标记     private boolean pagination=true;      //增强属性     //返回上一条请求的url路径     private String url;     //获取上一次请求的所有请求参数集合     private Map<String,String[]> maps;      public void setRequest(HttpServletRequest req){         //1、获取前端传入的分页三要素(page,rows,pagination)         String page = req.getParameter("page");         String rows = req.getParameter("rows");         String pagination = req.getParameter("pagination");          this.setPage(page);         this.setRows(rows);         this.setPagination(pagination);         //2、获取上一次请求的URL路径         //req.getContextPath == 获取项目名         //req.getServletPath() == 获取servlet请求路径名         //req.getRequestURL == req.getContextPath+req.getServletPath()         this.url=req.getRequestURI();         //3、获取上一次请求的所有请求参数集合         this.maps = req.getParameterMap();     }        /**      * 返回limit分页查询的开始位置      * @return      */     public int getStartIndex(){         return (this.page-1)*this.rows;     }      //重载set方法     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 setPagination(String pagination) {         if(null!=pagination)             this.pagination = Boolean.parseBoolean(pagination);     }      /**      * //分页方法      * //计算总分页      * @return 总分页数      */     public int getMaxPager(){         int max = this.total/this.rows;         //除不尽有余数         if(this.total%this.rows!=0)             max++;             return max;     }      /**      * 上一页方法      * @return 上一页页数      */     public int getPrevPager(){         int prev = this.page-1;         if(prev<=1)             prev=1;         return prev;     }      /**      * 下一页方法      * @return 下一页页数      */     public int getNextPager(){         int next=this.page+1;         if(next>=getMaxPager())             next=getMaxPager();         return next;     }      public String getUrl() {         return url;     }      public void setUrl(String url) {         this.url = url;     }      public Map<String, String[]> getMaps() {         return maps;     }      public void setMaps(Map<String, String[]> maps) {         this.maps = maps;     }      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 isPagination() {         return pagination;     }      public void setPagination(boolean pagination) {         this.pagination = pagination;     }      @Override     public String toString() {         return "PageBean{" +                 "page=" + page +                 ", rows=" + rows +                 ", total=" + total +                 ", pagination=" + pagination +                 ", url='" + url + '\'' +                 ", maps=" + maps +                 '}';     } } 

5.创建自定义分页标签

5.1.创建自定义分页标签助手类

package com.zking.pagintation.tag;  import com.zking.pagintation.uitl.PageBean;  import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; import java.util.Map; import java.util.Set;  public class PaginationTag extends BodyTagSupport {      private PageBean pageBean;      public PageBean getPageBean() {         return pageBean;     }      public void setPageBean(PageBean pageBean) {         this.pageBean = pageBean;     }      @Override     public int doStartTag() throws JspException {         try{             JspWriter out = pageContext.getOut();             out.print(toHtml());         }catch (Exception e){             e.printStackTrace();         }         return SKIP_BODY;     }      private String toHtml(){         //判断PageBean是否为空         if(null!=pageBean&&pageBean.isPagination()){             //定义StringBuffer可变字符串             //面试题:String/StringBuffer/StringBuilder/的区别             StringBuffer sb=new StringBuffer();             //拼接div跟标签             sb.append("<div style=\"float: right;\">");             //拼接form标签对象             sb.append("<form id=\"pageForm\" method=\"post\" action="+pageBean.getUrl()+">");             //拼接page隐藏域             sb.append(" <input type=\"hidden\" name=\"page\"/>");             //获取请求参数集合             Map<String,String[]> maps=pageBean.getMaps();             //获取请求参数集合的键值对             Set<Map.Entry<String, String[]>> entries = maps.entrySet();             //循环遍历请求参数键值对             for (Map.Entry<String, String[]> entry : entries) {                 //判断请求参数是否是page,如果是 则continue                 if(entry.getKey().equalsIgnoreCase("page"))                     continue;                 //获取请求参数的value值(类型为String[])                 String[] values = entry.getValue();                 //循环遍历value值                 for(String value : values){                     sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+value+"'>");                 }             }             sb.append("</form>");             //拼接分页信息             sb.append("第"+pageBean.getPage()+"页/总"+pageBean.getMaxPager()+"页数");             //拼接首页、上一页、下一页、末页             if(pageBean.getPage()==1)                 sb.append("首页&nbsp;上一页");             else {                 sb.append("<a onclick=\"gotoPage(1)\" href=\"javascript:void(0);\">首页</a>");                 sb.append("<a onclick=\"gotoPage("+pageBean.getPrevPager()+")\" href=\"javascript:void(0);\">上一页</a>");             }              if(pageBean.getPage()==pageBean.getMaxPager())                 sb.append("下一页&nbsp;末页");             else {                 sb.append("<a onclick=\"gotoPage("+pageBean.getNextPager()+")\" href=\"javascript:void(0);\">下一页</a>");                 sb.append("<a onclick=\"gotoPage("+pageBean.getMaxPager()+")\" href=\"javascript:void(0);\">末页</a>");             }             //拼接javascpit             sb.append("<script>\n" +                     "    function gotoPage(page){\n" +                     "        document.getElementById('pageForm').page.value=page;\n" +                     "        document.getElementById('pageForm').submit();\n" +                     "    }\n" +                     "</script>");             sb.append("</div>");             return sb.toString();         }         return "";     }      @Override     public int doEndTag() throws JspException {         return EVAL_PAGE;     } } 

5.2.导入标签描述文件

详见课件"z.tld"文件

 

5.3.自定义分页标签实现

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!