前言:上次与大家分享了自定义标签的知识,今天与大家分享的是关于通用分页的知识。大家看到这个标题时,通用二字是今天的重点,分页有前端和后台的代码。一一给大家讲解。
一:后台:
1、方法:
我们以上次的书籍表格为例,首先在dao包中写好代码,命名为basebao(基础包),写好方法:
public List<T> excuteQuery(String sql, Class<T> clz, PageBean pagebean) throws Exception {
List<T> list = new ArrayList<T>();
Connection con = DBAccess.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
// 当到后台时必须考虑的问题,看需不需要分页
if (pagebean != null && pagebean.isPagination()) {
// countsql 总数据数
String countsql = getCountsql(sql);
ps = con.prepareStatement(countsql);
rs = ps.executeQuery();
if(rs.next()) {
pagebean.setTotal(String.valueOf(rs.getObject(1)));
}
// pagesql 一页有多少条数据
String pagesql = getPagesql(sql, pagebean);
ps = con.prepareStatement(pagesql);
rs = ps.executeQuery();
} else {
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
}
while (rs.next()) {
T t = clz.newInstance();
Field[] fields = clz.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
f.set(t, rs.getObject(f.getName()));
}
list.add(t);
}
return list;
}
如上代码:里面是一个分页的代码,其中有几个参数大家要注意一下,分页主要是有total(总页数),countsql(总数据数),pagesql(第几页展示的数据,)
private String getCountsql(String sql) {
return "select count(1) from (" + sql + ")t ";
}
上面是得到所有的数据,还有得到哪一页要显示多少数据的方法。
/**
* 将原生sql转换为pagesql(第几页显示多少条数据)
* @param sql
* 原生sql
* @param pagebean
* 分页
* @return 是数据
*/
private String getPagesql(String sql, PageBean pagebean) {
return sql + "limit" + pagebean.getStartIndex() + "," + pagebean.getRows();
}
这就做到了通用思想,把分页中共用的东西写到一个包里面使得所有要用到分页的包继承这个包就可以了。
2:具体类方法:
public class BookDao extends BaseDao<Book> {
public List<Book> list(Book b) throws Exception {
List<Book> books = new ArrayList<Book>();
String sql = "select * from t_mvc_book where 1=1";
String bname = b.getBname();
if (StringUtils.isNotBlank(bname)) {
sql += "and bname like '%" +bname+ "%'";
}
Connection con = DBAccess.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
books.add(new Book(rs.getInt("bid"), rs.getString("bname"), rs.getFloat("price")));
}
return books;
}
//
public List<Book> list2(Book b) throws Exception {
String sql = "select * from t_mvc_book where 1=1";
String bname=b.getBname();
if(StringUtils.isBlank(bname)) {
sql="and bname like '%"+bname+"%'";
}
return super.list(sql,Book.class);
}
public List<Book> list3(Book book,PageBean pagebean) throws Exception {
String sql = "select * from t_mvc_book where 1=1";
String bookname = book.getBname();
if (StringUtils.isNotBlank(bookname)) {
sql += "and bname like '%" + bookname + "%'";
}
return super.excuteQuery(sql, Book.class, pagebean);
}
public static void main(String[] args) throws Exception {
BookDao bookdao = new BookDao();
Book book = new Book();
book.setBname("圣墟");
// List<Book> list = bookdao.list2(book);
PageBean pagebean=new PageBean();
pagebean.setPage(2);
List<Book> list = bookdao.list3(book,pagebean);
for (Book b : list) {
System.out.println(b);
}
}
}
上面是关于book的方法:其中三个都是查询的,其中list3是关于分页的,最后也在最后使用main方法查出来了对应的数据。
二:前端:
在开头也刚大家讲了通用分页包括前端和后台,接下来为大家讲解前端:
前端首先要显示界面,自己建一个tag标签包(PageTag),然后通过上节课学得知识自定义标签来写一个page标签,最后在index界面中直接写出自己定义的标签就行:下面代码展示:
class PageTag extends BodyTagSupport {
public int doStartTag() throws JspException {
JspWriter out = pageContext.getOut();
try {
out.print(toHtml());
} catch (IOException e) {
e.printStackTrace();
}
return super.doStartTag();
}
private String toHtml() {
//隐藏的form表单---这就是上一次重新发的奥义所在;
StringBuffer sb=new StringBuffer();
sb.append("<form action='' id='pageBeanForm' method='post'>");
sb.append(" <input type='hidden' name='page'>");
sb.append("</form>");
//分页条
sb.append("<ul class='pagination justify-content-center'>");
sb.append(" <li class='page-item'><a class='page-link'");
sb.append(" href='javascript:gotoPage(1)'>首页</a></li>");
sb.append(" <li class='page-item'><a class='page-link'");
sb.append(" href='javascript:gotoPage(1)'><</a></li>");
sb.append(" <li class='page-item'><a class='page-link' href='#'>1</a></li>");
sb.append(" <li class='page-item'><a class='page-link' href='#'>2</a></li>");
sb.append(" <li class='page-item active'><a class='page-link' href='#'>3</a></li>");
sb.append(" <li class='page-item disabled'><a class='page-link' href='#'>></a></li>");
sb.append(" <li class='page-item disabled'><a class='page-link' href='#'>尾页</a></li>");
sb.append(" <li class='page-item go-input'><b>到第</b><input class='page-link'");
sb.append(" type='text' id='skipPage' name='' /><b>页</b></li>");
sb.append(" <li class='page-item go'><a class='page-link'");
sb.append(" href='javascript:skipPage()'>确定</a></li>");
sb.append(" <li class='page-item'><b>共666条</b></li>");
sb.append("</ul>");
//分页执行的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");
sb.append(" || parseInt(page) > 1122) {");
sb.append(" alert('请输入1~N的数字');");
sb.append(" return;");
sb.append(" }");
sb.append(" gotoPage(page);");
sb.append(" }");
sb.append("</script>");
return sb.toString();
}
}
继承 BodyTagSupport类,用stringbuffer中的append方法来实现页面展示效果。
最后在index中写好 <z:page></z:page>即可。
三:关于分页的核心思想:
分页得核心思想:当点击下一页时,有许多参数是不变的,比如像名字,行数,以及总页数,但是其中有一个参数要变,那就是page(页数)。
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
private String url;
private Map<String, String[]> parammap = new HashMap<>();
public void setRequest(HttpServletRequest req) {
// 1、需要保存的url
this.setUrl(req.getRequestURI().toString());
// 2、需要保存上一次访问的参数
this.setParammap(req.getParameterMap());
// 3、需要 保存上一次的分页设置
this.setPagination(req.getParameter("pagination"));
// 4、需要保存上一次的分页的条目数
this.setRows(req.getParameter("rows"));
// 5、初始化请求的页码
this.setPage(req.getParameter("page"));
}
private void setPage(String page) {
if (StringUtils.isNotBlank(page)) {
this.setPage(Integer.valueOf(page));
}
}
private void setRows(String rows) {
if (StringUtils.isNotBlank(rows)) {
this.setRows(Integer.valueOf(rows));
}
}
private void setPagination(String pagination) {
if (StringUtils.isNotBlank(pagination)) {
this.setPagination(!"false".equals(pagination));
}
}
private void setPagination(boolean b) {
}
public Map<String, String[]> getParammap() {
return parammap;
}
public void setParammap(Map<String, String[]> parammap) {
this.parammap = parammap;
}
public PageBean() {
super();
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = 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;
}
/**
* 获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
/**
* 最大页数
*
* @return 最大数字
*/
public int maxPage() {
return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows + 1;
}
/**
* 求上一页的页数
*
* @return
*/
public int nextPage() {
return this.page < this.maxPage() ? this.page + 1 : this.page;
}
/**
* 求下一页数据
*
* @return
*/
public int previousPage() {
return this.page > 1 ? this.page - 1 : this.page;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
}
上面是分页类中的代码。
总结:通用分页把它简单化就分成前端和后台,其中公用的写到一个类里面就能减少代码量和大量时间,要抓住核心思想,这样才能事半功倍。