文章目录
前言
分页的后台代码链接通用分页(一)
为什么使用自定义标签
因为通用分页是为了节省代码,增加代码的重用性,自定义标签也是一样。自定义标签原理就不介绍了下方有链接
自定义标签
代码详解
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()+"页 <a ");
sb.append(" href='javascript:gotoPage(1)'>首页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getPreviousPage()+")'>上一页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getNextPage()+")'>下一页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a> ");
sb.append(" <input type='text' id='skipPage'");
sb.append(" style='text-align: center; font-size: 12px; width: 50px;'> <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();
}
}
效果图
总结
通用分页到这里就完成了,过两天我会把完整源码分享出来,如果有什么不对的地方欢迎大家在评论区留言交流改进!!