通用分页(二)

前言

分页的后台代码链接通用分页(一)

为什么使用自定义标签

因为通用分页是为了节省代码,增加代码的重用性,自定义标签也是一样。自定义标签原理就不介绍了下方有链接
自定义标签

代码详解

pageBean的优化

pageBean新增了两个属性
	private Map<String, String[]> parMap =new HashMap<>();//获取到jsp页面所有的参数以及参数值
	private String url;//获取到请求路径

方法:

	/**
	 *	获取最大页码数
	 * @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;
	}
}
public void setRequest(HttpServletRequest req) {
		//能够获取到jsp页面所有的参数以及参数值
		//Map<String, String[]> parameterMap = req.getParameterMap();
		//能够获取到请求路径
		//StringBuffer requestURL = req.getRequestURL();
		this.setParMap(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;
	}

注意看文中注释,重点都打了注释

BaseDao的优化,使用反射实例化。
package com.liuchunming.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.liuchunming.entity.Book;

/**
 * T代表你要对哪个实体类对应的表进行分页查询
 * @author chunming
 *
 * @param <T>
 */
public class BaseDao<T> {
	/**
	 * 
	 * @param sql 查询不同的实体类那么对应sql语句不同,所以需要传递
	 * @param clz 生产出不同的实体类对应的实例,然后装进list容器中返回
	 * @param pageBean 决定是否分页
	 * @return
	 * @throws SQLException
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public List<T> executeQuery(String sql, Class clz,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
		Connection con = DBAccess.getConnection();
		PreparedStatement ps=null;
		ResultSet rs=null;
		
		if(pageBean!=null && pageBean.isPagination()) {
			//需要分页
			//算符合条件的总记录数
			String countSql = getCountSql(sql);
			ps = con.prepareStatement(countSql);
			rs = ps.executeQuery();
			if(rs.next()) {
				pageBean.setTotal(rs.getLong(1)+"");
			}
			
			//查询出符合条件的结果集
			String pageSql = getPageSql(sql,pageBean);
			ps = con.prepareStatement(pageSql);
			rs = ps.executeQuery();
		}else {
			ps = con.prepareStatement(sql);
			rs = ps.executeQuery();
		}
		
		List<T> list = new ArrayList<T>();
		T t;//节省内存
		while(rs.next()) {
		 t = (T) clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				field.set(t, rs.getObject(field.getName()));
			}
			list.add(t);
		}
		DBAccess.close(con, ps, rs);
		return list;
	}
	/**
	 * 拼接出符合条件结果集的查询sql
	 * @param sql 
	 * @param pageBean
	 * @return
	 */
	private String getPageSql(String sql, PageBean pageBean) {
		return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();
	}
	/**
	 * 获取符合条件的总记录数
	 * @param sql
	 * @return
	 */
	private String getCountSql(String sql) {
		String countsql=" select count(1) from ("+sql+") t";
		return countsql;
	}
}

使用反射的好处,查询方法代码明显减少了
	/**
	 * 
	 * @param book 封装的jsp传递过来的查询参数
	 * @param pageBean 决定dao层list调用时是否分页
	 * @return 
	 * @throws SQLException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public List<Book> list(Book book,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
		String sql=" select * from t_mvc_book where true";
		String bname =book.getBname();
		if(StringUtils.isNotBlank(bname)) {
			sql+=" and bname like '%"+bname+"%'";
		}
		return super.executeQuery(sql, Book.class, pageBean);
	}

结合自定义标签类开发通用分页标签:自定义标签创建标签库描述文件和标签助手类,将前端代码以字符串拼接的方式封装进标签助手类。

描述标签库
<!-- 标签库描述符 -->
<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>/liuchunming</uri>
	<!-- empty标签 -->
	
	<tag>
		<name>page</name>
		<tag-class>com.liuchunming.tag.PageTag</tag-class>
		<body-content>empty</body-content>
		<attribute>
			<name>pageBean</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>
</taglib>
Tag助手类
package com.liuchunming.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.liuchunming.util.PageBean;

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) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return super.doStartTag();
	}
	private String toHtml() {
		StringBuffer sb =new StringBuffer();
		//拼接下一次发送请求索要提交的隐藏的form表单
		sb.append("<form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>");
		sb.append("<input type='hidden' name='page'>");
		Map<String, String[]> parMap = pageBean.getParMap();
		if(parMap!=null&&parMap.size()>0) {
			Set<Entry<String,String[]>> entrySet = parMap.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()+"页&nbsp;&nbsp;<a ");
		sb.append(" 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;");
		sb.append(" <input type='text' 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();
	}
}

注:助手类有很多重要的地方需要注意
写完然后在jsp界面上引用就行了

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="l" uri="/liuchunming" %>
<body>
	<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>
	<l:page pageBean="${pageBean }"/>
</body>

最后是控制层后台处理分页代码

	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 pageBean =new PageBean();
		try {
			pageBean.setRequest(req);
			List<Book> list = this.bookDao.list(book, pageBean);
			req.setAttribute("bookList", list);
			req.setAttribute("pageBean", pageBean);
			req.getRequestDispatcher("/bookList.jsp").forward(req, resp);;
		} catch (InstantiationException | IllegalAccessException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

效果图

在这里插入图片描述
在这里插入图片描述

总结

通用分页到这里就完成了,过两天我会把完整源码分享出来,如果有什么不对的地方欢迎大家在评论区留言交流改进!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值