通用分页的核心
.将上一次查询请求再发一次,只不过改变了页码。
本章重点:
1、改造上次PageBean里 的内容;
2、页面展示
3、创建控制层 servlet
4、自定义分页标签
5、助手类信息
1. PageBean
分页三要素
page 页码 视图层传递过来
rows 页大小 视图层传递过来
total 总记录数 后台查出来
pagination 是否分页 视图层传递过来
2. 后台
2.1 entity
2.2 dao
第一次查满足条件的总记录数
第二次查指定页码并满足条件的记录
二次查询的条件要一致
2.3 控制层
Servlet
3. 视图层
PageTag
如何将上一次查询请求再发一次
String contextPath = req.getContextPath();//根目录
String url = req.getServletPath();//请求的地址
req.getRequestURL() //获取请求全路径
Map<String, String[]> parameterMap = req.getParameterMap();//获得请求中的所有参数
PageBean:
package com.lww.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
private Map<String, String[]> paMap = new HashMap<>();
private String url;
public void setRequest(HttpServletRequest req) {
Map<String, String[]> parameterMap = req.getParameterMap();
StringBuffer url = req.getRequestURL();
//保存上一次请求所携带的参数
this.setPaMap(req.getParameterMap());
this.setUrl(req.getRequestURL().toString());
//在jsp页面来控制是否分页
// this.setPagination(req.getParameter("pagination"));
//在jsp页面控制一页展示多少条信息
// this.setRows(req.getParameter("rows"));
this.setPage(req.getParameter("page"));
}
private void setPage(String page) {
this.page = StringUtils.isNotBlank(page) ? Integer.valueOf(page):this.page;
}
public void setPagination(String pagination) {
this.pagination = StringUtils.isNotBlank(pagination) ? !"false".equals(pagination):this.pagination;
}
public void setRows(String rows) {
this.rows = StringUtils.isNotBlank(rows)?Integer.valueOf(rows):this.rows;
}
public Map<String, String[]> getPaMap() {
return paMap;
}
public void setPaMap(Map<String, String[]> paMap) {
this.paMap = paMap;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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;
}
/**
* 获得起始记录的下标
*/
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 getMaxPage() {
return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows+1;
}
/**
* 下一页
*/
public int getNexPage() {
return this.page < this.getMaxPage() ? this.page+1 : this.page;
}
/**
* 上一页
*/
public int getPreviousPage() {
return this.page > 1 ? this.page-1 : this.page;
}
}
为了展示jsp页面效果,分页代码插入到了控制层的Servlet里面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%@taglib prefix="z" uri="/lww" %> <!-- 导入自定义标签库使用自定义的分页标签 -->
<%@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">
<title>Insert title here</title>
</head>
<body>
<c:if test="${empty bookList }">
<jsp:forward page="bookServlet.action"></jsp:forward>
</c:if>
<h2>小说目录</h2>
<br>
<form action="${pageContext.request.contextPath}/bookServlet.action"
method="post">
书名:<input type="text" name="bname"> <input type="submit"
value="确定">
<input type="hidden" name="pagination" value="false">
<input type="hidden" name="rows" value="20">
</form>
<table border="1" width="100%">
<tr>
<td>编号</td>
<td>名称</td>
<td>价格</td>
</tr>
<c:forEach items="${bookList }" var="s">
<tr>
<td>${s.bid }</td>
<td>${s.bname }</td>
<td>${s.price}</td>
</tr>
</c:forEach>
</table>
<z:Page pageBean="${pageBean }"></z:Page>
</body>
</html>
控制层Servlet
package com.lww.web;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.BookDao;
import entity.Book;
import util.PageBean;
public class BookServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
private BookDao bookDao = new BookDao();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String bname = req.getParameter("bname");
Book book = new Book();
book.setBname(bname);
//
PageBean bean = new PageBean();
try {
bean.setRequest(req);
List<Book> list = this.bookDao.list(book,bean);
req.setAttribute("bookList", list);
req.setAttribute("pageBean", bean);
req.getRequestDispatcher("/BookList.jsp").forward(req, resp);
} catch (InstantiationException | IllegalAccessException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app id="WebApp_ID">
<display-name>Test_pagebean</display-name>
<servlet> <servlet-name>bookServlet</servlet-name>
<servlet-class>com.web.BookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bookServlet</servlet-name>
<url-pattern>/bookServlet.action</url-pattern>
</servlet-mapping> </web-app>
自定义分页标签
package com.lww.web;
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 util.PageBean;
public class PageTag extends BodyTagSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doStartTag();
}
private String toHTML() {
StringBuilder sb= new StringBuilder();
sb.append("<form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>");
sb.append("<input type='hidden' name='page'>");
Map<String, String[]> paMap = pageBean.getPaMap();
if(paMap != null && paMap.size()>0) {
Set<Entry<String, String[]>> entrySet = paMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
//上一次请求可能携带页码name=page的参数,但是改参数在前面已经单独赋值,
//因为上一次请求是第一页的数据,下一次可能是第二页,一位这前后请求page对应的值是不一样的,需要单独赋值
if(!"page".equals(entry.getKey())) {
for(String val:entry.getValue()) {
sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+val+"'>");
}
}
}
}
sb.append("</form>");
//拼接分页条
sb.append("<div style='text-align: right; font-size: 12px;'>");
sb.append("每页"+pageBean.getRows()+"条,共"+pageBean.getTotal()+"条,第"+pageBean.getPage()+"页,共"+pageBean.getMaxPage()+"页 <a ");
sb.append(" href='javascript:gotoPage(1)'>首页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getPreviousPage()+")'>上一页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getNexPage()+")'>下一页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a> <input type='text'");
sb.append(" id='skipPage'");
sb.append(" style='text-align: center; font-size: 12px; width: 50px;'> <a");
sb.append(" href='javascript:skipPage()'>Go</a>");
sb.append("</div>");
//拼接分页所需要的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)>"+pageBean.getMaxPage()+"){");
sb.append(" alert('请输入1~N的数字');");
sb.append(" return;");
sb.append(" }");
sb.append(" gotoPage(page);");
sb.append(" }");
sb.append(" </script>");
return sb.toString();
}
}(注意在拼接时需要注意空格)
将自定义标签的类配到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的版本 -->
<jsp-version>1.2</jsp-version>
<!-- 你的标签库的简称 -->
<short-name>test</short-name>
<!-- 你标签库的引用uri -->
<uri>/zking</uri>
<!-- 1自定义分页标签 -->
<tag>
<name>Page</name> //标签库中的标签名
<tag-class>com.tag.PageTag</tag-class>//标签的助手类全路径名
<body-content>JSP</body-content>
<attribute>
<name>pageBean</name>//标签属性名 在配置的时候必须与助手类的属性一致
<required>true</required>//该属性是否必填
<rtexprvalue>true</rtexprvalue>//是否支持表达式(EL)
</attribute>
</tag>
</taglib>
助手类信息StringUtils :
package 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);
}
}
EncodingFiter :(中文乱码处理)
package 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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 中文乱码处理
*
*/
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();
}
}
}
jsp页面效果如下:
目录:

下一页:

上一页:

尾页:

跳转:
