🥳🥳Welcome Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于通用分页的相关操作吧
目录
🥳🥳Welcome Huihui's Code World ! !🥳🥳
导言:
上一篇博客我们已经将后端的代码后端的代码编写完毕了👇👇(主要就是通用分页的查询方法),那么此篇博客我们将编写的是前端的代码,并且完成标签的编写,如果你已经准备好了,那就让我们一起往下看吧!
最终效果
在开始编写代码之前,先让我们看看最终我们所完成的效果是怎么样的吧!!
看完效果演示之后,是不是更加想知道怎么完成分页标签的制作了呢!!
分页的核心思想
1.优化完善JavaBean
1.1案例分析
- 第一次我们进入首页,输入“圣墟”之后点击查询,在我们后台处理的时候需要拿到的参数有哪些呢?
- page=1,rows=10,bname=“圣墟”,pagination=“true”,url=本次所作请求的请求路径
- 点击下一页,在我们后台处理的时候需要拿到的参数有哪些呢?
- page=2,rows=10,bname=“圣墟”,pagination=“true”,url=本次所作请求的请求路径
- 点击下一页,在我们后台处理的时候需要拿到的参数有哪些呢?
- page=3,rows=10,bname=“圣墟”,pagination=“true”,url=本次所作请求的请求路径
- ...
- ...
1.2通过上述的分析,我们可以找到规律👆
- 即每次做出下一页的操作时,我们传的参数好像大致都相同,但是也有会些许的参数不同,而这个不同的地方,却也有规律
- 每一次当我们点击下一页的时候,都只有page这个参数的值发生了变化,当然不管是上一页还是下一页,都是一样的,不过是增减的区别而已
1.3😵优化pagebean😵
- 这一些参数我们都需要将其保留,定义在pagebean中,以及每次的请求路径【因为它们都没有发生变化,每次都需要使用到这些参数】
- 而当我们点击上一页下一页的时候,相应的page也要发生改变,所以在pagebean中也需要创建这两个方法
- 并且我们需要拿到前台传到servlet中的参数,把pagebean初始化
2.完成通用分页的标签
2.1标签助手类
- 将标签中的内容做好拼接【request中的属性,不拼接page的属性,因为只有page会发生变化,那就将page这个参数做一个表单提交】
- 处理分页条上面的页数显示,以当前的页码为基准,如果当前页码大于4的话,那么在它的前面就还有4个页码的值,如果不大于4的话,那么当前的页码减一后的结果就是在此页码前面所显示的页码的数量,本页码后面显示的就是用总共要显示的数量减一再减去在本页码之前所有的页码的数量
- 假设当前页面是5的话,那么它前面就是有1-4这几个页码,后面就是6-10
- 在上一页和下一页的按钮上,还有首页和尾页的按钮上都设置有同一个方法,就是改变页码的方法,如果当前也是第一页了,那么就不能在点击上一页和首页的按钮【禁用】,如果当前是最后一页了也是一样的,尾页和下一页的按钮不能够在点击了【禁用】
- 显示总页数/总条数...都是直接第哦啊用pagebean中的方法
- 跳转到指定的页码,需要做判断,不为空,不为非数字,不小于最小,不大于最大
2.2tld标签库描述文件
- 命名为page,其中的参数的命名也需要规范好,以及助手类的全路径名需要写好【如果对自定义标签有问题可以点击下面的链接】
思路以及分析完毕,那么接下来让我们直接上代码!!!
一.完善Pagebean
- 需要新增变量保存上一次查询条件
- 需要新增变量保存上一次请求地址
- 需要添加方法:获取最大页的页码
- 需要添加方法:获取下一页的页码
- 需要添加方法:获取上一页的页码
- 需要新增方法:初始化pagebean
package com.wh.util; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; /** * 分页工具类 * @author W * */ 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; } }
二. 通用分页的标签
1.助手类
package com.wh.tag; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.servlet.jsp.tagext.JspTag; import com.wh.util.PageBean; import java.io.IOException; import java.util.Map; import java.util.Set; /** * 分页标签的助手类 * @author W * */ 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.getParameterMap(); 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~"+pageBean.getMaxPage()+"的数字');"); sb.append("return;"); sb.append("}"); sb.append("gotoPage(page);"); sb.append("}"); sb.append("</script>"); return sb.toString(); } }
2.tld标签库描述文件
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <!-- 标签库描述符 --> <taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor"> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Simple Tags</short-name> <uri>wh</uri> <!-- 分页标签 --> <tag> <!-- 标签名 --> <name>page</name> <!-- 助手类路径 --> <tag-class>com.wh.tag.PageTag</tag-class> <!--不是空标签 --> <body-content>JSP</body-content> <!--属性 --> <attribute> <!-- 属性名 --> <name>pageBean</name> <!--是否必填 --> <required>true</required> <!-- 是否可以用EL表达式 --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
3.jsp页面引用
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="wh" prefix="w" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!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 }/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 "> <thead> <tr> <th scope="col">书籍ID</th> <th scope="col">书籍名</th> <th scope="col">价格</th> </tr> </thead> <tbody> <c:if test="${empty books }"> <jsp:forward page="book.action"></jsp:forward> </c:if> <c:if test="${not empty books }"> <c:forEach items="${books }" var="b"> <tr> <td>${b.bid }</td> <td>${b.bname }</td> <td>${b.price }</td> </tr> </c:forEach> </c:if> </tbody> </table> <w:page pageBean="${pageBean }"></w:page> </body> </html>
三.解决中文乱码
我们在进行模糊查询的时候,需要输入关键字,但是当我们没有自主的去解决编码问题的话,那么在页面上将不会展示模糊查询的结果,而会是看到一堆乱码,我们可以看一下没有解决编码问题的时候会是怎么样的效果
那么我们通过什么方法来解决这个问题呢?答案是使用过滤器!!将编码统一设置
package com.wh.util; import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 中文乱码处理 * @author W * */ @WebFilter("*.action") public class EncodingFiter implements Filter { private String encoding = "UTF-8";// 默认字符集 public EncodingFiter() { super(); } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // 中文处理必须放到 chain.doFilter(request, response)方法前面 res.setContentType("text/html;charset=" + this.encoding); if (req.getMethod().equalsIgnoreCase("post")) { req.setCharacterEncoding(this.encoding); } else { Map map = req.getParameterMap();// 保存所有参数名=参数值(数组)的Map集合 Set set = map.keySet();// 取出所有参数名 Iterator it = set.iterator(); while (it.hasNext()) { String name = (String) it.next(); String[] values = (String[]) map.get(name);// 取出参数值[注:参数值为一个数组] for (int i = 0; i < values.length; i++) { values[i] = new String(values[i].getBytes("ISO-8859-1"), this.encoding); } } } chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { String s = filterConfig.getInitParameter("encoding");// 读取web.xml文件中配置的字符集 if (null != s && !s.trim().equals("")) { this.encoding = s.trim(); } } }
那么我们再来看看解决编码问题之后的效果
通过两篇博客的讲述,相信你也已经大致掌握了通用分页的操作了吧,我们可以看到,完成一个分页的效果,还是需要编写许多代码的,但是我们现在通过把它们封装成标签的形式,在以后的使用中,就只需要一行代码就能够完成(在页面上引用标签)。分页的代码少说也是以千来计数的,我们要是按照以前的方式去写代码,当我们需要在7个页面用到分页,那么就需要写7000+的代码,而且都是重复代码,但现在写一遍受用终身!!
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊