在小编前面的博客中,有诉说过通用分页的前奏
,大家可以去结合起来使用及阅读,不然有头没有尾,是个程序员一般都会一脸懵逼,串连接不起来,是毫无能用的代码,当然,如果是大佬级别,可以自己去探索摸索它的后续,本章博客是**通用分页的优化
,是真的强大,建议使用这个版本的“通用分页
”,在这里提供“通用分页(一)
**”的入口:
链接: 通用分页(一).
效果图中的功能:
1、能够查询全部
的数据
2、界面中能够展示 ‘每页多少条数据’ ‘总共查询到多少条’ ‘当前是第几页’ ‘总共查询到多少页’,根据自己的数据库
来
3、能够点击“首页
”,“上一页
”,“下一页
”,“尾页
” 直接跳转
4、能够在“文本框
”中输入你想要的“页数
”,再点击“GO
”直接跳转显示你想要的数据
5、能够在“书名
”后的文本框
中输入内容,再点击“确定
”,可以进行相对应的模糊查,能够完成前面“4
”点的功能,
因为通用分页的核心思想是“将上一次的查询请求再发一次,只不过是页码变了
”
今天的代码会用到web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>T243_pagebean</display-name>
<!--配置字符编码过滤器 -->
<filter>
<filter-name>encodingFiter</filter-name>
<filter-class>com.xiaoqing.util.EncodingFiter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFiter</filter-name>
<servlet-name>*.action</servlet-name>
</filter-mapping>
<!--BookServlet的配置 -->
<servlet>
<servlet-name>bookServlet</servlet-name>
<servlet-class>com.xiaoqing.web.BookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bookServlet</servlet-name>
<url-pattern>/bookServlet.action</url-pattern>
</servlet-mapping>
<!--jobServlet配置 -->
<servlet>
<servlet-name>jobServlet</servlet-name>
<servlet-class>com.xiaoqing.web.JobServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jobServlet</servlet-name>
<url-pattern>/jobServlet.action</url-pattern>
</servlet-mapping>
</web-app>
讲解此类的作用:
在我们写各种servlet的类时,dopost方法前首先先要设置字符编码,每个servlet类都要经历编码解码这个过程,这样会重复很多的代码,所以我们在这里写一个通用的类,以后只要有如下两行代码,就可以用这个类代替,那么在dopost的方法中我们就可以省略此两行,直接在你的项目中的web.xml中配置EncodingFiter的servlet就OK,方便开发者少写很多重复的代码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
EncodingFiter类的内容(此类中为节少代码量,把导包去掉了,如复制有误,哪里报错就"Alt+/“按哪里表示导包,不要导错包,不然无用,需要的包有"util”、“io”、“servlet”,如有其他的包应该会没有作用):
/**
* 中文乱码处理
*
*/
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();
}
}
}
为什么说这个功能比较强大呢,我们先来对比一下
例如:
String bname=req.getParameter("bname");
此上行代码是获取jsp界面传过来的参数值,如果一次带过来的参数有很多个,是不是得要写很多行
例如:
String bname=req.getParameter("bname");
String bid=req.getParameter("bid");
String price=req.getParameter("price");
String page=req.getParameter("page");
String sum=req.getParameter("sum");
..................
是不是发现每行的代码基本上都一样,只需要改属性名及接收的名字,那么我们是不是可以想想怎么一步到位呢?来了,真的来咯!
//能够获取jsp页面传过来的所有参数以及传输值
Map<String, String[]> parameterMap = req.getParameterMap();
就是此上这一行代码,就能完成上述功能,无论你带多少个值都没问题,既然接收的是map集合,所以直接遍历就好了,本章博客中,是先定义一个private的map集合,再给它放进去,请仔细看代码,理解逻辑很重要
StringUtils类中的代码在链接: 通用分页(一).中有
//如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
public void setRows(String rows) {
this.rows = StringUtils.isNotBlank(rows)?Integer.valueOf(rows):this.rows;//三元运算符,如果rows是不为空,就把本应该是String类型的转int类型,为空返回它本身的数据类型
}
此上方法在pageBean中重写,有朋友疑问这样有什么好处呢?好处大大的,作为开发者,肯定要开发快,并且效率也要高,那么就不会写很多繁琐重复的代码,并且还要安全性强,我在设置属性时就给判断是否为空,后面开发不只一次调用这个属性,那我就可以不用每一次调用时就判断了,直接调用就好,是开发者都想要代码量少,并且要开发效率快,不只这一个属性可以,以后需要判断是否为空的都可以调用StringUtils类中两个方法,非常"通用"
,小编认为这比较强大,建议使用
**主要应用:**各种数据类型之间的转换
pageBean中的内容(此类中为节少代码量,把导包去掉了,如复制有误,哪里报错就"Alt+/"按哪里表示导包,不要导错包):
/**
* 分页工具类
*
*/
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<String, String[]>();
private String url;
public void setRequest(HttpServletRequest req) {
//保存上一次请求携带的参数this.setPaMap(req.getParameterMap());
//获取上一次请求的路径url
this.setUrl(req.getRequestURL().toString());
//在jsp页面来控制是否分页
this.setPagination(req.getParameter("pagination"));
//在jsp页面控制一页展示多少条数据
this.setRows(req.getParameter("rows"));
//获取当前是第几页
this.setPage(req.getParameter("page"));
}
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() {
}
public int getPage() {
return page;
}
public void setPage(String page) {
this.page =StringUtils.isNotBlank(page)?Integer.valueOf(page):this.page;
}
public int getRows() {
return rows;
}
public void setRows(String rows) {
this.rows = StringUtils.isNotBlank(rows)?Integer.valueOf(rows):this.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(String pagination) {
this.pagination = StringUtils.isNotBlank(pagination)?!"false".equals(pagination):this.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 + "]";
}
/**
* 获取最大的页码数
* @return
*/
public int getMaxPage() {
return this.total%this.rows==0?this.total/this.rows:this.total/this.rows+1;
}
/**
* 获取下一页
* @return
*/
public int getNextPage() {
return this.page<this.getMaxPage()?this.page+1:this.page;
}
/**
* 获取上一页
* @return
*/
public int getPreviousPage() {
return this.page>1?this.page-1:this.page;
}
}
比较难理解重要的知识点已在上面几点中讲解了,pageBean就改造OK了
自定义标签描述助手类的内容:
若看不懂,不太理解自定义标签,这里提供链接: "自定义标签".的知识点,方便去回顾,所以在此处就不多啰嗦啦!!!!!!!!!!!
<?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>zking 1.1 core library</description>
<display-name>zking core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>z</short-name>
<uri>/xiaoqing</uri>
<tag>
<!-- 标签库中的标签(类似c:set c:out的定义) -->
<name>page</name>
<!-- 是标签运行具体代码,也是助手类,下面填写的是助手类的全路径名 -->
<tag-class>com.xiaoqing.tag.PageTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<!-- 该标签的属性 -->
<name>pageBean</name>
<!-- 该属性是否必填 -->
<required>true</required>
<!-- 是否支持表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
PageTag标签类中的内容(此类中为节少代码量,把导包去掉了,如复制有误,哪里报错就"Alt+/"按哪里表示导包,不要导错包):
package com.xiaoqing.tag;
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.xiaoqing.util.PageBean;
public class PageTag extends BodyTagSupport {
private static final long serialVersionUID = -258029245678348536L;
private PageBean pageBean;
public PageBean getPageBean() {
return pageBean;
}
public void setPageBean(PageBean pageBean) {
this.pageBean = pageBean;
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
JspWriter out = pageContext.getOut();
try {
out.print(toHTML());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doStartTag();
}
/**
* 拼接html代码
* @return
*/
public String toHTML() {
StringBuilder sb=new StringBuilder();
//拼接下一次发送请求所要提交的隐藏的form表单
//System.out.println(pageBean.getUrl());
sb.append(");
sb.append("");
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())) {
//<input type='hidden' name='hobby'> value='1'>
//<input type='hidden' name='hobby'> value='1'>
//[1,2]
for (String val : entry.getValue()) {
sb.append(" ");
}
}
}
}
sb.append("");
sb.append("");
sb.append("");
//拼接分页条
sb.append("");
sb.append("每页"+pageBean.getRows()+"条,共"+pageBean.getTotal()+"条,第"+pageBean.getPage()+"页,共"+pageBean.getMaxPage()+"页 首页 );
sb.append(" href='javascript:gotoPage("+pageBean.getPreviousPage()+")'>上一页 );
sb.append(" href='javascript:gotoPage("+pageBean.getNextPage()+")'>下一页 );
sb.append(" href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页 );
sb.append(" id='skipPage'");
sb.append(" style='text-align: center; font-size: 12px; width: 50px;'> );
sb.append(" href='javascript:skipPage()'>Go");
sb.append("");
//拼接分页所需要的js代码
sb.append("");
return sb.toString();
}
}
然后运行bookList.jsp界面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="z" uri="/xiaoqing"%>
<!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>"WebContent/jobList.jsp"
<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="b">
<tr>
<td>${b.bid }</td>
<td>${b.bname }</td>
<td>${b.price }</td>
</tr>
</c:forEach>
</table>
<z:page pageBean="${pageBean }"></z:page>
<!--把上一次的请求在发一次 -->
<form id='pageBeanForm' action='' method='post'>
<input type='hidden' name=''> <input type='hidden' name='page'>
</form>
</body>
</html>
最终的结果就是前面截图显示的模样!!!!!
整个通用分页就OK了!!!!
希望能够帮助你们!!!!
感谢支持!!!
大胆的问一句能要一个"双击加关注吗"!!
感谢!!!
小编的博客中如有误,还请朋友们留言指导。嘻嘻嘻!!!!!