本章目标:
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()
+ "页 <a href='javascript:gotoPage(1)'>首 页</a> <a href='javascript:gotoPage("
+ pageBean.getPreviousPage() + ")'>上一页</a> <a href='javascript:gotoPage("
+ pageBean.getNextPage() + ")'>下一页</a> <a href='javascript:gotoPage(" + pageBean.getMaxPage()
+ ")'>末 页</a> <input id='skipPage' type='text' style='text-align: center;font-size: 12px;width:50px;'> <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();
}
通用分页
最新推荐文章于 2023-11-02 11:21:45 发布