通用分页

3 篇文章 0 订阅
本章目标:
1.完成基本的数据绑定
2.创建PageBean实现分页及查询分页
3.创建JSP自定义分页标签

====================================================

通用分页核心思路:
  将上一次查询请求再发一次,只是当前页变了而已。


1.完成基本的数据绑定
  搭建一个web项目,实现数据的完整绑定
  1.1 创建数据库
  1.2 创建动态web项目,并创建好相应包:
	action
	biz
	dao		第一次查满足条件的总记录数
			第二次查指定页码并满足条件的记录
			二次查询的条件要一致
	entity
	utils
 
  1.2 前端JSP
      index.jsp 点击查看
      list.jsp  书籍列表

     
2.实现基本的数据展示
  2.1 创建BaseDao,实现基本数据涉及到泛型,内部静态接口,resultSet转集合类等。

3.分页工具类PageBean
  分页三要素:
   	currentPage	当前页	        视图层传递过来
   	pageSize	每页显示记录数	视图层传递过来
   	totalCount	总记录数	后台查出来
	pagination  	是否分页	视图层传递过来

4.JSP分页标签
  标签助手类:PageTag
  标签描述文件
  JSP表单提交分页
   

5. JUnit
   java单元测试/白盒测试
   setUp
   tearDown 
   测试用例
   

==============================================================================
1.完成基本的数据绑定中注意事项
  (1)BaseDao类中的executeQuery方法为查询的封装方法:
       public List<T> executeQuery(String sql, CallBack<T> callBack){

  (2)接收各DaoImpl中传递进来的SQL语句到数据库进行查询,查询出的结果通过内部静态接口实现类进行转换。
	//静态回调接口
	public static interface CallBack<E>{
	    //方法:将结果集转换成集合
	    public List<E> forEach(ResultSet rs) throws Exception;
	}

	//调用接口实现类将结果集转换成集合
	list = callBack.forEach(rs);

  (3)转换类实现BaseDao类中的内部静态接口,重写forEach(),将接收到的result结果集转换成List集合
	public class BookRsToList implements BaseDao.CallBack<Book> {
	    @Override
	    public List<Book> forEach(ResultSet rs) throws Exception {
		List<Book> bookList = new ArrayList<>();
		while(rs.next()) {
		    Book b = new Book(rs.getInt("rm"), rs.getString("code"), rs.getString("name"));
		    bookList.add(b);
		}
		return bookList;
	}

==============================================================================
2.分页工具类PageBean
  分析:先实现所有数据分页,再考虑模糊查询分页
  (1)创建分页工具类PageBean,封装分页三要素:
	private Integer currentPage = 1;	//当前页
	private Integer pageSize = 10;	// 页大小
	private Integer totalCount = 0;	// 总记录数
	private Boolean pagination = true;	//是否分页
  (2)封装分页方法
	//获得每页起始下标
	public int getStartIndex() {
	    return (this.currentPage - 1) * this.pageSize;
	}

	//上一页
	public int getPreviousPage() {
	    return this.currentPage > 1 ? this.currentPage-1 : 1; 
	}

	//下一页
	public int getNextPage() {
		return this.currentPage < getMaxPage() ? this.currentPage+1:getMaxPage();
	}
	
	//末页(最大页)
	public int getMaxPage() {
		int maxPage = this.totalCount / this.pageSize;
		if(this.totalCount % this.pageSize!=0) {
			maxPage++;
		}
		return maxPage;
	}
  (3)Servlet源文件中实例pageBean,将从前端接收currentPage和pageSize赋值,同时可以设置pagination
  (4)将pageBean对象传递给BaseDao中的executeQuery(),进行重点处理:
	//第一次查满足条件的总记录数
	if (null != pageBean && pageBean.isPagination()) {
	    String countSql = this.getCountSql(sql);  //调用getCountSql()方法对SQL进行统计处理
	    countPs = conn.prepareStatement(countSql);
	    countRs = countPs.executeQuery();
	    if (countRs.next()) {
		//注意数据库的count(*)返回值类型,兼容Long/Integer两种类型
		pageBean.setTotalCount(Integer.parseInt(countRs.getObject(1).toString()))
	    }
	    DBAccess.close(null, countPs, countRs);
	}

	//第二次查指定页码并满足条件的记录
	if (null != pageBean && pageBean.isPagination()) {
	    sql = this.getPageSql(sql, pageBean);  //调用getPageSql()方法对SQL进行分页处理
	}

  (5)对SQL进行处理:将普通的sql转换成查总记录数的getCountRows()
	SQL语句:select count(*) from ( select * from news where 1=1 ntitle like '%1%' ) t1;
	private String getCountSql(String sql){
	    return "select count(*) from (" + sql + ") t1";
	}

  (6)对SQL进行处理:求总页数的方法getPageSql()
	private String getPageSql(String sql, PageBean pageBean){
	    return sql+" limit " + pageBean.getStartIndex() + "," + pageBean.getRows();
	}

3.搜索条件分页
  在实现所有数据分页的基础上,只需修改XxxDaoImpl中方法的SQL语句
  (1)在JSP页面添加搜索表单
	<form action="pageSerlvet.do" method="post">
	    搜索关键词:<input type="text" name="searchKey" value="" /><input type="submit" value="搜索" />
	</form>	
  (2)Servlet中封装搜索对象Book
	Book book = new Book();
	if(StringUtils.isNotBlank(req.getParameter("searchKey"))){
	    book.setName(req.getParameter("searchKey").trim());
	}
  (3)BookDaoImpl类中的
	@Override
	public List<Book> getBooks(PageBean pageBean, Book book) {
	    String sql = "select * from t_book where 1=1 ";
	    if(book != null && StringUtils.isNotBlank(book.getName())) {
		sql = sql + " and name like '%"+ book.getName() +"%'";
	    }
	……

蒋奇:大中型项目,没有讲技术,太短

==============================================================================
4.JSP分页标签
  问题:如何将上一次查询请求再发一次?
	a:获得上次的请求	
	b:获得上次的参数key

  (1)在Servlet中添加源代码
	//第1:获得上次的请求
	String contextPath = req.getContextPath(); //获得项目地址
	String url = req.getServletPath(); //获得上次请求的地址

	//第2:获得上次的参数key  -> Map("key",value)
	Map<String, String[]> parameterMap = req.getParamterMap();  //获得请求中的所有参数,包括关键中、当前页
		
	再点分页链接时,再发一次请求。

  (2)在PageBean中封装两属性:
	private String url;	//根目录+请求地址
	private Map<String,String[]> paramerMap;	//请求参数

  (3)对PageBean属性进行初始化设置
	public void setRequest(HttpServletRequest request) {
	    //获值
	    String currentPage = request.getParameter("currentPage");
	    String pageSize = request.getParameter("pageSize");
	    String pagination = request.getParameter("pagination");
	    //设置值
	    if(currentPage != null){ this.setCurrentPage(Integer.parseInt(currentPage))};
	    if(pageSize != null) {this.setPageSize(Integer.parserInt(pageSize));
	    if(pagination != null) {this.setPagination(Boolean.parseBoolean(pagination));

	    //提交路径及参数(将上一次查询请求再发一次,只不过页码变了)
	    this.url = request.getContextPath() + request.getServletPath();
	    this.parameterMap = request.getParameterMap();
	}


  (4)创建PageTag类,做自定义JSP标签
	第一步:创建PageTag类,继承BodyTagSupport。
	第二步:封装PageBean属性(因为得到PageBean对象,就能得到分页的元素)
	第三步:重写doStartTag()方法,向JSP页面输入
		JspWriter out = pageContext.getOut();
		out.println(this.toHTML());
		return SKIP_BODY;
	第四步:编写toHTML()方法,返回拼接的String。

  (5)JSP页面
	引入标签库:<%@ taglib prefix="x" uri="/pageBean" %>
	使用标签:<x:page pageBean="${pageBean}" />
	
=========================================================================

private String toHTML() {
    if (null == pageBean || !pageBean.isPagination()) {
	return "";
    }
    StringBuffer bf = new StringBuffer();
    // 生成表单及参数
    bf.append("<form id='pageBeanForm' action='" + this.pageBean.getUrl() + "' method='post'>");
    bf.append("<input type='hidden' name='page' value=''>");

    String name = null;
    String[] values = null;

    for (Map.Entry<String, String[]> entry : pageBean.getParameterMap().entrySet()) {
	name = entry.getKey();
	if ("page".equals(name)) {
	    continue;   // 通过js代码修改
	}
	values = entry.getValue();
	for (String value : values) {
	    bf.append("<input type='hidden' name='" + name + "' value='" + value + "'>");
	}
    }
    bf.append("</form>");

    // 生成分页按钮
    bf.append("<div style='text-align: right;font-size: 12px;'>每页" + this.getPageBean().getRows() + "条,共"
	+ this.pageBean.getTotal() + "条,第" + pageBean.getPage() + "页,共" + pageBean.getMaxPage()
	+ "页&nbsp;&nbsp;<a href='javascript:gotoPage(1)'>首&nbsp;&nbsp;页</a>&nbsp;&nbsp;<a href='javascript:gotoPage("
	+ pageBean.getPreviousPage() + ")'>上一页</a>&nbsp;&nbsp;<a href='javascript:gotoPage("
	+ pageBean.getNextPage() + ")'>下一页</a>&nbsp;&nbsp;<a href='javascript:gotoPage(" + pageBean.getMaxPage()
	+ ")'>末&nbsp;&nbsp;页</a>&nbsp;&nbsp;<input id='skipPage' type='text' style='text-align: center;font-size: 12px;width:50px;'>&nbsp;&nbsp;<a href='javascript:skipPage();'>GO</a></div>");

    // 生成jsi{

    bf.append("<script>");
    bf.append("function gotoPage(page){");
    bf.append("  document.getElementById('pageBeanForm').page.value = page;");
    bf.append("  document.getElementById('pageBeanForm').submit();");
    bf.append("}");
    bf.append("var maxPage="+pageBean.getMaxPage()+";");
    bf.append("function skipPage(){");
    bf.append("  var page = document.getElementById('skipPage').value;");
    bf.append("  if(!page||isNaN(page)||parseInt(page)<1||parseInt(page)>maxPage){");
    bf.append("    alert('请输入1~8之间的数字');");
    bf.append("    return;");
    bf.append("  }");
    bf.append("  gotoPage(page);");
    bf.append("}");
    bf.append("</script>");

    return bf.toString();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值