1.分页
- 数据信息较多的的时候一般采用列表显示,方便展示信息;
- 数据量较大的时候一般采用列表加分页的方式显示,便于阅读。
- 分页方式:集合或者session、存储过程、SQL语句分页
2.分页步骤
- 确定每页显示的数据数量
- 确定分页显示所需的总页数
- 编写SQL查询语句,实现数据查询
- 在JSP页面中进行分页显示设置
- 对分页过程中的数据进行封装,封装到Page类中
3.实列
3.1DBAccess类对mysql数据库进行连接访问
package com.xuyahui.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * 提供了一组获得或关闭数据库对象的方法 * */ public class DBAccess { private static String driver; private static String url; private static String user; private static String password; static {// 静态块执行一次,加载 驱动一次 try { InputStream is = DBAccess.class .getResourceAsStream("config.properties"); Properties properties = new Properties(); properties.load(is); driver = properties.getProperty("driver"); url = properties.getProperty("url"); user = properties.getProperty("user"); password = properties.getProperty("pwd"); Class.forName(driver); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 获得数据连接对象 * * @return */ public static Connection getConnection() { try { Connection conn = DriverManager.getConnection(url, user, password); return conn; } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static void close(ResultSet rs) { if (null != rs) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Statement stmt) { if (null != stmt) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Connection conn) { if (null != conn) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Connection conn, Statement stmt, ResultSet rs) { close(rs); close(stmt); close(conn); } public static boolean isOracle() { return "oracle.jdbc.driver.OracleDriver".equals(driver); } public static boolean isSQLServer() { return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver); } public static boolean isMysql() { return "com.mysql.cj.jdbc.Driver".equals(driver); } public static void main(String[] args) { Connection conn = DBAccess.getConnection(); System.out.println(conn); DBAccess.close(conn); System.out.println("isOracle:" + isOracle()); System.out.println("isSQLServer:" + isSQLServer()); System.out.println("isMysql:" + isMysql()); System.out.println("数据库连接(关闭)成功"); } }
3.2编写实体类
package com.xuyahui.entity; /** * @author 小徐 * @com.xuyahui.entity * @Book(说明):书(实体类) */ public class Book { private int bid; private String bname; private float price; @Override public String toString() { return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]"; } public int getBid() { return bid; } public void setBid(int bid) { this.bid = bid; } public String getBname() { return bname; } public void setBname(String bname) { this.bname = bname; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public Book(int bid, String bname, float price) { super(); this.bid = bid; this.bname = bname; this.price = price; } public Book() { super(); } }
3.3方法类
package com.xuyahui.Dao; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import com.xuyahui.entity.Book; import com.xuyahui.util.DBAccess; import com.xuyahui.util.PageBean; public class BaseDao<T> { /** * 带分类的模糊查询 * @param sql * @param clz * @param pageBean * @return * @throws Exception */ public List<T> executeQuery(String sql,Class clz,PageBean pageBean) throws Exception{ List<T> list = new ArrayList<T>(); Connection conn = null; PreparedStatement pst = null; ResultSet rs = null; if(pageBean != null && pageBean.isPagination()) { String countSQL = getCountSQL(sql); conn = DBAccess.getConnection(); pst = conn.prepareStatement(countSQL); rs = pst.executeQuery(); if(rs.next()) { pageBean.setTotal(rs.getObject("n").toString()); } String pageSQL = getPageSQL(sql,pageBean); conn = DBAccess.getConnection(); pst = conn.prepareStatement(pageSQL); rs = pst.executeQuery(); }else { conn = DBAccess.getConnection(); pst = conn.prepareStatement(sql); rs = pst.executeQuery(); } while(rs.next()) { T t = (T) clz.newInstance();//反射 // 拿到clz对应的所有属性对象 Field[] fields = clz.getDeclaredFields();//拿到属性 for (Field f : fields) { f.setAccessible(true); f.set(t, rs.getObject(f.getName()));//保存属性 } list.add(t); } return list; //最后循坏遍历 } /** * 拼接处最终展示数据的sql * @param sql 原生sql * @return */ private String getCountSQL(String sql) { return "select count(1) as n from ("+sql+") t"; } /** * 拼接处查询符合条件的总记录数SQL * @param sql * @param pageBean * @return */ private String getPageSQL(String sql, PageBean pageBean) { return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows(); } }
3.4工具类
package com.xuyahui.util; public class StringUtils { // 私有的构造方法,保护此类不能在外部实例化 private StringUtils() { } /** * 如果字符串等于null或去空格后等于"",则返回true,否则返回false * * @param s * @return */ public static boolean isBlank(String s) { boolean b = false; if (null == s || s.trim().equals("")) { b = true; } return b; } /** * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false * * @param s * @return */ public static boolean isNotBlank(String s) { return !isBlank(s); } }
3.5帮助类
package com.xuyahui.util; import java.io.IOException; import java.util.Map; import java.util.Set; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; /** * @author 小徐 * @com.xuyahui.entity * @PageTag(说明):标签帮助类 */ public class PageTag extends BodyTagSupport { private PageBean pageBean; public PageBean getPageBean() { return pageBean; } public void setPageBean(PageBean pageBean) { this.pageBean = pageBean; } @Override public int doStartTag() throws JspException { JspWriter out = pageContext.getOut(); try { out.print(toHTML()); } catch (IOException e) { e.printStackTrace(); } return SKIP_BODY; } private String toHTML() { StringBuilder sb = new StringBuilder(); // 这里拼接的是一个上一次发送的请求以及携带的参数,唯一改变的就是页码 sb.append("<form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>"); // sb.append("<input type='hidden' name='methodName' value='list'>"); sb.append("<input type='hidden' name='page'>"); // 重要设置拼接操作,将上一次请求参数携带到下一次 Map<String, String[]> paMap = pageBean.getPageMap(); if(paMap !=null && paMap.size()>0){ Set<Map.Entry<String, String[]>> entrySet = paMap.entrySet(); for (Map.Entry<String, String[]> entry : entrySet) { for (String val : entry.getValue()) { if(!"page".equals(entry.getKey())){ sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+val+"'>"); } } } } sb.append("</form>"); int page = pageBean.getPage(); int max = pageBean.getMaxPage(); int before = page > 4 ? 4 : page-1; int after = 10 - 1 - before; after = page+after > max ? max-page : after; // disabled boolean startFlag = page == 1; boolean endFlag = max == page; // 拼接分页条 sb.append("<ul class='pagination'>"); sb.append("<li class='page-item "+(startFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage(1)'>首页</a></li>"); sb.append("<li class='page-item "+(startFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getPrevPage()+")'><</a></li>"); // 代表了当前页的前4页 for (int i = before; i > 0 ; i--) { sb.append("<li class='page-item'><a class='page-link' href='javascript:gotoPage("+(page-i)+")'>"+(page-i)+"</a></li>"); } sb.append("<li class='page-item active'><a class='page-link' href='javascript:gotoPage("+pageBean.getPage()+")'>"+pageBean.getPage()+"</a></li>"); // 代表了当前页的后5页 for (int i = 1; i <= after; i++) { sb.append("<li class='page-item'><a class='page-link' href='javascript:gotoPage("+(page+i)+")'>"+(page+i)+"</a></li>"); } sb.append("<li class='page-item "+(endFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getNextPage()+")'>></a></li>"); sb.append("<li class='page-item "+(endFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a></li>"); sb.append("<li class='page-item go-input'><b>到第</b><input class='page-link' type='text' id='skipPage' name='' /><b>页</b></li>"); sb.append("<li class='page-item go'><a class='page-link' href='javascript:skipPage()'>确定</a></li>"); sb.append("<li class='page-item'><b>共"+pageBean.getTotal()+"条</b></li>"); sb.append("</ul>"); // 拼接分页的js代码 sb.append("<script type='text/javascript'>"); sb.append("function gotoPage(page) {"); sb.append("document.getElementById('pageBeanForm').page.value = page;"); sb.append("document.getElementById('pageBeanForm').submit();"); sb.append("}"); sb.append("function skipPage() {"); sb.append("var page = document.getElementById('skipPage').value;"); sb.append("if (!page || isNaN(page) || parseInt(page) < 1 || parseInt(page) > "+max+") {"); sb.append("alert('请输入1~N的数字');"); sb.append("return;"); sb.append("}"); sb.append("gotoPage(page);"); sb.append("}"); sb.append("</script>"); return sb.toString(); } }
pageBean工具类
package com.xuyahui.util; import java.util.Map; import javax.servlet.http.HttpServletRequest; /** * @author 小徐 * @com.xuyahui.utils * @PageBean(说明):分页工具类 */ public class PageBean { private int page = 1;// 页码 private int rows = 10;// 页大小 private int total = 0;// 总记录数 private boolean pagination = true;// 是否分页 private String url; private Map<String, String[]> pageMap; public void setRequest(HttpServletRequest req) { // 初次进入jsp页面传递过来的当前页 this.setPage(req.getParameter("page")); // 初次进入jsp页面传递过来的页大小 this.setRows(req.getParameter("rows")); // 初次进入jsp页面传递过来是否分页 this.setPagination(req.getParameter("pagination")); // 保留上一次的查询请求 this.setUrl(req.getRequestURL().toString()); // 保留上一次的查询条件 this.setPageMap(req.getParameterMap()); } public void setPagination(String pagination) { // 只有填写了false字符串,才代表不分页 this.setPagination(!"false".equals(pagination)); } public void setRows(String rows) { if (StringUtils.isNotBlank(rows)) this.setRows(Integer.valueOf(rows)); } public void setPage(String page) { if (StringUtils.isNotBlank(page)) this.setPage(Integer.valueOf(page)); } // 上一页 public int getPrevPage() { return this.page > 1 ? this.page - 1 : this.page; } // 下一页 public int getNextPage() { return this.page < this.getMaxPage() ? this.page + 1 : this.page; } // 最大页 public int getMaxPage() { return this.total % this.rows == 0 ? this.total / this.rows : (this.total / this.rows) + 1; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map<String, String[]> getPageMap() { return pageMap; } public void setPageMap(Map<String, String[]> pageMap) { this.pageMap = pageMap; } public PageBean() { super(); } 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 void setTotal(String total) { this.total = Integer.parseInt(total); } public boolean isPagination() { return pagination; } public void setPagination(boolean pagination) { this.pagination = pagination; } /** * 获得起始记录的下标 * @return */ public int getStartIndex() { return (this.page - 1) * this.rows; } @Override public String toString() { return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]"; } }
3.6界面使用
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html > <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script> <title>书籍列表</title> <style type="text/css"> .page-item input { padding: 0; width: 40px; height: 100%; text-align: center; margin: 0 6px; } .page-item input, .page-item b { line-height: 38px; float: left; font-weight: 400; } .page-item.go-input { margin: 0 10px; } </style> </head> <body> <form class="form-inline" action="${pageContext.request.contextPath }/book.action" method="post"> <div class="form-group mb-2"> <input type="text" class="form-control-plaintext" name="bname" placeholder="请输入书籍名称"> </div> <button type="submit" class="btn btn-primary mb-2">查询</button> </form> <table class="table table-striped bg-success"> <thead> <tr> <th scope="col">书籍ID</th> <th scope="col">书籍名</th> <th scope="col">价格</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>圣墟第1章</td> <td>1</td> </tr> <tr> <td>1</td> <td>圣墟第1章</td> <td>1</td> </tr> </tbody> </table> <form action="" id="pageBeanForm" method="post"> <input type="hidden" name="page"> </form>zzz <ul class="pagination justify-content-center"> <li class="page-item"><a class="page-link" href='javascript:gotoPage(1)'>首页</a></li> <li class="page-item"><a class="page-link" href='javascript:gotoPage(1)'><</a></li> <li class="page-item"><a class="page-link" href="#">1</a></li> <li class="page-item"><a class="page-link" href="#">2</a></li> <li class="page-item active"><a class="page-link" href="#">3</a></li> <li class="page-item disabled"><a class="page-link" href="#">></a></li> <li class="page-item disabled"><a class="page-link" href="#">尾页</a></li> <li class="page-item go-input"><b>到第</b><input class="page-link" type="text" id="skipPage" name="" /><b>页</b></li> <li class="page-item go"><a class="page-link" href="javascript:skipPage()">确定</a></li> <li class="page-item"><b>共666条</b></li> </ul> <script type='text/javascript'> function gotoPage(page) { document.getElementById('pageBeanForm').page.value = page; document.getElementById('pageBeanForm').submit(); } function skipPage() { var page = document.getElementById('skipPage').value; if (!page || isNaN(page) || parseInt(page) < 1 || parseInt(page) > 1122) { alert('请输入1~N的数字'); return; } gotoPage(page); } </script> </body> </html>
效果及作用