通用分页(二)

前言

在小编前面的博客中,有诉说过通用分页的前奏,大家可以去结合起来使用及阅读,不然有头没有尾,是个程序员一般都会一脸懵逼,串连接不起来,是毫无能用的代码,当然,如果是大佬级别,可以自己去探索摸索它的后续,本章博客是**通用分页的优化,是真的强大,建议使用这个版本的“通用分页”,在这里提供“通用分页(一)**”的入口:

链接: 通用分页(一).

1、最终运行效果

效果图中的功能:

1、能够查询全部的数据
2、界面中能够展示 ‘每页多少条数据’      ‘总共查询到多少条’      ‘当前是第几页’      ‘总共查询到多少页’,根据自己的数据库

3、能够点击“首页”,“上一页”,“下一页”,“尾页” 直接跳转
4、能够在“文本框”中输入你想要的“页数”,再点击“GO”直接跳转显示你想要的数据
5、能够在“书名”后的文本框中输入内容,再点击“确定”,可以进行相对应的模糊查,能够完成前面“4”点的功能,
因为通用分页的核心思想是“将上一次的查询请求再发一次,只不过是页码变了

在这里插入图片描述

今天的代码会用到web.xml配置文件

2、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>

3、字符编码的作用,EncodingFiter字符编码过滤器

讲解此类的作用
在我们写各种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();
		}
	}

}

4、重要的知识点及功能强大的地方,给开发者提供便捷的途径

4.1.req.getParameterMap()

为什么说这个功能比较强大呢,我们先来对比一下
例如:

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集合,再给它放进去,请仔细看代码,理解逻辑很重要

4.2、重载方法的好处,例:pageBean类中的setRows()

StringUtils类中的代码在链接: 通用分页(一).中有

//如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
public void setRows(String rows) {
		this.rows = StringUtils.isNotBlank(rows)?Integer.valueOf(rows):this.rows;//三元运算符,如果rows是不为空,就把本应该是String类型的转int类型,为空返回它本身的数据类型
	}

此上方法在pageBean中重写,有朋友疑问这样有什么好处呢?好处大大的,作为开发者,肯定要开发快,并且效率也要高,那么就不会写很多繁琐重复的代码,并且还要安全性强,我在设置属性时就给判断是否为空,后面开发不只一次调用这个属性,那我就可以不用每一次调用时就判断了,直接调用就好,是开发者都想要代码量少,并且要开发效率快,不只这一个属性可以,以后需要判断是否为空的都可以调用StringUtils类中两个方法,非常"通用",小编认为这比较强大,建议使用

**主要应用:**各种数据类型之间的转换

5、pageBean的改造

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了

6、通用分页标签的编写(打包成自定义标签)

自定义标签描述助手类的内容:
若看不懂,不太理解自定义标签,这里提供链接: "自定义标签".的知识点,方便去回顾,所以在此处就不多啰嗦啦!!!!!!!!!!!

<?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("<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())) {
					//<input type='hidden' name='hobby'> value='1'>
					//<input type='hidden' name='hobby'> value='1'>
					//[1,2]
					for (String val : entry.getValue()) {
						sb.append("<input type='hidden' name='"+entry.getKey()+"'value='"+val+"'> ");
					}
				}
			}
		}
		sb.append("</form>");
		sb.append("");
		sb.append("");
		//拼接分页条
		sb.append("<div style='text-align: right; font-size: 12px;'>");
		sb.append("每页"+pageBean.getRows()+"条,共"+pageBean.getTotal()+"条,第"+pageBean.getPage()+"页,共"+pageBean.getMaxPage()+"页&nbsp;&nbsp;<a href='javascript:gotoPage(1)'>首页</a>&nbsp;&nbsp;<a");
		sb.append(" href='javascript:gotoPage("+pageBean.getPreviousPage()+")'>上一页</a>&nbsp;&nbsp;<a");
		sb.append(" href='javascript:gotoPage("+pageBean.getNextPage()+")'>下一页</a>&nbsp;&nbsp;<a");
		sb.append(" href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a>&nbsp;&nbsp;<input type='text'");
		sb.append(" id='skipPage'");
		sb.append("	style='text-align: center; font-size: 12px; width: 50px;'>&nbsp;&nbsp;<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();
	}
}

然后运行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了!!!!
希望能够帮助你们!!!!

感谢支持!!!
大胆的问一句能要一个"双击加关注吗"!!
感谢!!!
小编的博客中如有误,还请朋友们留言指导。嘻嘻嘻!!!!!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值