前言:
上次发布了一篇关于通用查询分页,这篇这继上篇加优化以及演示,比上篇更加清晰明了,
有些只给了代码但是没有详细分析的请看上篇博客,谢谢!
一.分页
Java的分页功能通常在Web开发中用于展示数据列表的分页显示。这种场景下,数据量可能非常庞大,如果一次性将所有记录都展示出来,会导致页面加载缓慢,用户体验不佳。
分页功能可以将数据分为多个页面展示,每个页面仅包含一定数量的记录,大大提高了页面加载速度和响应时间,增强了用户体验。此外,分页功能还可以支持用户自行选择每页显示的记录数和跳转到指定页面的功能,更加满足用户的需求。
二.分页的步骤
- 编写一份要展示数据的属性,实体类
- 定义需要的属性或者关于分页的方法,放在分页工具类里面 PageBean.java,这个方法里面的东西,比较难,看下面的核心思想
- 编写通用Dao方法,我运用了BaseDao方法(这个方法我在上篇已经写了)
- 写助手类,主要就是进行拼接展示
- 自定义标签,编写tld文件
- 编写前端展示页面 jsp文件,导入自定义标签库
- servlet类,获取数据并进行保存,然后回显给前端 jsp文件
- 最后执行,展示效果
我们来看看分页的核心思想是什么?
前面也说了这篇是优化上篇我所写的通用查询,主要优化了PageBean
- 增加了一个属性URL,来保存上一次发送的请求地址
- 增加了一个属性ParamMap,来保存模糊查询所携带的参数
- 增加三个方法 :最大页,下一页,上一页
- 最后初始化pageBean方法
实体类的代码:
package com.yinzi.entity; 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; } }
三.分页工具类
老规矩,还是先上整体代码,再分析
分页工具类代码:
package com.yinzi.utils; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; /** * 分页工具类 * */ public class PageBean { private int page = 1;// 页码 private int rows = 10;// 页大小 private int total = 0;// 总记录数 // 上一次查询的url private String url; // 上一次查询所携带的查询条件 private Map<String, String[]> parameterMap = new HashMap<String, String[]>(); // 对pagebean进行初始化 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.setParameterMap(req.getParameterMap()); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map<String, String[]> getParameterMap() { return parameterMap; } public void setParameterMap(Map<String, String[]> parameterMap) { this.parameterMap = parameterMap; } private void setPagination(String pagination) { // 只有填写了false字符串,才代表不分页 this.setPagination(!"false".equals(pagination)); } private void setRows(String rows) { if (StringUtils.isNotBlank(rows)) this.setRows(Integer.valueOf(rows)); } private void setPage(String page) { if (StringUtils.isNotBlank(page)) this.setPage(Integer.valueOf(page)); } private boolean pagination = true;// 是否分页 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 + "]"; } // 上一页 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; } }
3.1 详解分页工具类
这里我每一行都打了注释,都是很详细的,这一步就是初始化,在初始化时,需要定义三个方法
然后编写分页所需要的方法
四.助手类
这里主要都是拼接,展示,然后编写分页的功能
package com.yinzi.servlet; import java.io.IOException; 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.yinzi.utils.PageBean; public class BookTag 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 (Exception e) { e.printStackTrace(); } return super.doStartTag(); } /** * 拼接的方法 * @return */ private String toHTML() { StringBuffer sb = new StringBuffer(); // form sb.append("<form action=\""+pageBean.getUrl()+"\" id=\"pageBeanForm\" method=\"post\">"); sb.append(" <input type=\"hidden\" name=\"page\">"); Map<String, String[]> paramMap = pageBean.getParameterMap(); if(paramMap != null && paramMap.size() > 0) { Set<Entry<String, String[]>> entrySet = paramMap.entrySet(); for (Entry<String, String[]> entry : entrySet) { String name = entry.getKey(); String[] value = entry.getValue(); if(value != null && value.length > 0) { for (String val : value) { if(!"page".equals(entry.getKey())){ sb.append(" <input type=\"hidden\" name=\""+name+"\" value=\""+val+"\">"); } } } } } sb.append("</form>"); // 分页条 sb.append("<ul class=\"pagination justify-content-center\">"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == 1 ? "disabled" : "")+"\"><a class=\"page-link\""); sb.append(" href='javascript:gotoPage(1)'>首页</a></li>"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == 1 ? "disabled" : "")+"\"><a class=\"page-link\""); sb.append(" href='javascript:gotoPage("+pageBean.getPrevPage()+")'><</a></li>"); sb.append(" <li class=\"page-item\"><a class=\"page-link\" href=\"#\">"+pageBean.getPage()+"</a></li>"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == pageBean.getMaxPage() ? "disabled" : "")+"\"><a class=\"page-link\" href=\"javascript:gotoPage("+pageBean.getNextPage()+")\">></a></li>"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == pageBean.getMaxPage() ? "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\""); sb.append(" type=\"text\" id=\"skipPage\" name=\"\" /><b>页</b></li>"); sb.append(" <li class=\"page-item go\"><a class=\"page-link\""); sb.append(" 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"); sb.append(" || parseInt(page) > 1122) {"); sb.append(" alert('请输入1~N的数字');"); sb.append(" return;"); sb.append(" }"); sb.append(" gotoPage(page);"); sb.append(" }"); sb.append("</script>"); return sb.toString(); } }
五.编写tld文件
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>JSTL 1.1 core library</description> <display-name>JSTL core</display-name> <tlib-version>1.1</tlib-version> <short-name>y</short-name> <uri>http://yinzi</uri> <tag> <!-- 标签库标签的名字 --> <name>page</name> <!-- 对应的助手类 --> <tag-class>com.yinzi.servlet.BookTag</tag-class> <!-- 代表JSP标签 --> <body-content>JSP</body-content> <!-- 属性 --> <attribute> <!-- 属性名称 --> <name>pageBean</name> <!-- 是否为必填项 --> <required>true</required> <!-- 是否支持EL表达式 --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
六,前端展示页面和Servlet界面
前端页面代码:
<%@ 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="http://yinzi" prefix="y" %> <!DOCTYPE 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"> <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 }/BookServlet.do" 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 "> <thead> <tr> <th scope="col">书籍ID</th> <th scope="col">书籍名</th> <th scope="col">价格</th> </tr> </thead> <tbody> <c:forEach items="${books}" var="b"> <tr> <td>${b.bid }</td> <td>${b.bname }</td> <td>${b.price }</td> </tr> </c:forEach> </tbody> </table> <y:page pageBean="${pageBean }"></y:page> </body> </html>
servlet代码:
package com.yinzi.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.yinzi.dao.BookDao; import com.yinzi.entity.Book; import com.yinzi.utils.PageBean; @WebServlet("/BookServlet.do") public class BookServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //实例化dao方法,来调用查询的方法 BookDao bookDao = new BookDao(); //实例化分页工具类,调取初始化方法 PageBean pageBean = new PageBean(); pageBean.setRequest(request); //实例化实体类 Book book = new Book(); //获取模糊查询的参数 book.setBname(request.getParameter("bname")); try { //调用查询的方法 List<Book> list = bookDao.queryAll(book , pageBean); //保存 request.setAttribute("books", list); request.setAttribute("pageBean", pageBean); //跳转 request.getRequestDispatcher("/book.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); } } }
详解Servlet:基本上都是调用方法,注释每一行都有
最后展示效果: