1.封装工具类:
1.1分析数据:
1.首先我们要根据需求拿到要分页展示的数据(如:Mysql)
2.定义需要的mysql语句
3.找到共同特点简化代码
1.2数据配置文件
这里封装了一个管理数据库连接类,可根据自生电脑情况来修改内容
#oracle9i #driver=oracle.jdbc.driver.OracleDriver #url=jdbc:oracle:thin:@localhost:1521:orcl #user=scott #pwd=123 #sql2005 #driver=com.microsoft.sqlserver.jdbc.SQLServerDriver #url=jdbc:sqlserver://localhost:1433;DatabaseName=test1 #user=sa #pwd=123 #sql2000 #driver=com.microsoft.jdbc.sqlserver.SQLServerDriver #url=jdbc:microsoft:sqlserver://localhost:1433;databaseName=unit6DB #user=sa #pwd=888888 #mysql driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=UTF-8&useSSL=false user=root pwd=123456
1.3数据库帮助类
提供了一组获得或关闭数据库对象的方法
package com.xzs.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * 提供了一组获得或关闭数据库对象的方法 * */ public class DBAccess { private static String driver; private static String url; private static String user; private static String password; static {// 静态块执行一次,加载 驱动一次 try { InputStream is = DBAccess.class .getResourceAsStream("config.properties"); Properties properties = new Properties(); properties.load(is); driver = properties.getProperty("driver"); url = properties.getProperty("url"); user = properties.getProperty("user"); password = properties.getProperty("pwd"); Class.forName(driver); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 获得数据连接对象 * * @return */ public static Connection getConnection() { try { Connection conn = DriverManager.getConnection(url, user, password); return conn; } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static void close(ResultSet rs) { if (null != rs) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Statement stmt) { if (null != stmt) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Connection conn) { if (null != conn) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } } public static void close(Connection conn, Statement stmt, ResultSet rs) { close(rs); close(stmt); close(conn); } public static boolean isOracle() { return "oracle.jdbc.driver.OracleDriver".equals(driver); } public static boolean isSQLServer() { return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver); } public static boolean isMysql() { return "com.mysql.cj.jdbc.Driver".equals(driver); } public static void main(String[] args) { Connection conn = DBAccess.getConnection(); System.out.println(conn); DBAccess.close(conn); System.out.println("isOracle:" + isOracle()); System.out.println("isSQLServer:" + isSQLServer()); System.out.println("isMysql:" + isMysql()); System.out.println("数据库连接(关闭)成功"); } }
1.4字节码过滤器
将不是utf-8的文件给过滤出来,中文乱码处理
package com.xzs.util; import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 中文乱码处理 * */ public class EncodingFiter implements Filter { private String encoding = "UTF-8";// 默认字符集 public EncodingFiter() { super(); } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // 中文处理必须放到 chain.doFilter(request, response)方法前面 res.setContentType("text/html;charset=" + this.encoding); if (req.getMethod().equalsIgnoreCase("post")) { req.setCharacterEncoding(this.encoding); } else { Map map = req.getParameterMap();// 保存所有参数名=参数值(数组)的Map集合 Set set = map.keySet();// 取出所有参数名 Iterator it = set.iterator(); while (it.hasNext()) { String name = (String) it.next(); String[] values = (String[]) map.get(name);// 取出参数值[注:参数值为一个数组] for (int i = 0; i < values.length; i++) { values[i] = new String(values[i].getBytes("ISO-8859-1"), this.encoding); } } } chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { String s = filterConfig.getInitParameter("encoding");// 读取web.xml文件中配置的字符集 if (null != s && !s.trim().equals("")) { this.encoding = s.trim(); } } }
1.5字符串判空类
package com.xzs.util; public class StringUtils { // 私有的构造方法,保护此类不能在外部实例化 private StringUtils() { } /** * 如果字符串等于null或去空格后等于"",则返回true,否则返回false * * @param s * @return */ public static boolean isBlank(String s) { boolean b = false; if (null == s || s.trim().equals("")) { b = true; } return b; } /** * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false * * @param s * @return */ public static boolean isNotBlank(String s) { return !isBlank(s); } }
1.6分页工具类(pagebean)
package com.xzs.util; /** * 分页工具类 * */ public class PageBean { private int page = 1;// 页码 private int rows = 10;// 页大小 private int total = 0;// 总记录数 private boolean pagination = true;// 是否分页 public PageBean() { super(); } 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; } public void setPagination(boolean pagination) { this.pagination = pagination; } /** * 获得起始记录的下标 * * @return */ public int getStartIndex() { return (this.page - 1) * this.rows; } @Override public String toString() { return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]"; } }
2.通用分页(后端)
2.1数据变量
package com.xzs.entity; public class Book { private int bid; private String bname; private float price; @Override public String toString() { return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]"; } public int getBid() { return bid; } public void setBid(int bid) { this.bid = bid; } public String getBname() { return bname; } public void setBname(String bname) { this.bname = bname; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
2.2原生dao层(该方法拿到所有的数据)
package com.xzs.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import com.xzs.entity.Book; import com.xzs.util.DBAccess; import com.xzs.util.PageBean; import com.xzs.util.StringUtils; public class Bookdao { public List<Book> list(Book book,PageBean pageBean) throws Exception{ List<Book> list = new ArrayList<Book>(); Connection con = DBAccess.getConnection(); String sql = "select * from t_mvc_book where 1=1 "; String bname = book.getBname(); if(StringUtils.isNotBlank(bname)) { sql += "and bname like '%"+bname+"%' "; } PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery(); while(rs.next()) { list.add(new Book(rs.getInt("bid"), rs.getString("bname"), rs.getFloat("price"))); } return list; } }
2.3BaseDao分页方法
package com.xzs.dao; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import com.xzs.util.DBAccess; import com.xzs.util.PageBean; public class BaseDao<T> { public List<T> executeQuery(String sql,PageBean pageBean,Class<T> clz) throws Exception{ List<T> list = new ArrayList<T>(); Connection con = DBAccess.getConnection(); PreparedStatement pst = null; ResultSet rs = null; String countSQL = getCountSQL(sql); String pageSQL = getPageSQL(sql,pageBean); if(pageBean != null && pageBean.isPagination()) { pst = con.prepareStatement(countSQL); rs = pst.executeQuery(); if(rs.next()) { pageBean.setTotal(String.valueOf(rs.getObject(1))); } pst = con.prepareStatement(pageSQL); rs = pst.executeQuery(); }else { pst = con.prepareStatement(sql); rs = pst.executeQuery(); } while(rs.next()) { // list.add(new Book(rs.getInt("bid"), rs.getString("bname"), rs.getFloat("price"))); 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; } private String getPageSQL(String sql, PageBean pageBean) { return sql + " limit "+pageBean.getStartIndex()+","+pageBean.getRows(); } private String getCountSQL(String sql) { return "select count(1) FROM ("+sql+") t"; } }
2.4BookDao的分页方法
package com.xzs.dao; import java.sql.Connection; import java.util.ArrayList; import java.util.List; import com.xzs.entity.Book; import com.xzs.util.DBAccess; import com.xzs.util.PageBean; import com.xzs.util.StringUtils; public class BookDao1 extends BaseDao { public List<Book> list(Book book,PageBean pageBean) throws Exception{ List<Book> list = new ArrayList<Book>(); Connection con = DBAccess.getConnection(); String sql = "select * from t_mvc_book where 1=1 "; String bname = book.getBname(); if(StringUtils.isNotBlank(bname)) { sql += "and bname like '%"+bname+"%' "; } return super.executeQuery(sql, pageBean, book.getClass()); } }
运行结果为:
3.分页通用(前端)
3.1分页的核心思想
3.2优化pagebean
package com.xzs.util; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; /** * 分页工具类 * */ public class PageBean1 { private int page = 1;// 页码 private int rows = 10;// 页大小 private int total = 0;// 总记录数 // 上一次查询的url private String url; // 上一次查询所携带的查询条件 private Map<String, String[]> parameterMap = new HashMap<String, String[]>(); // 对pagebean进行初始化 public void setRequest(HttpServletRequest req) { // 初始化jsp页面传递过来的当前页 this.setPage(req.getParameter("page")); // 初始化jsp页面传递过来的页大小 this.setRows(req.getParameter("rows")); // 初始化jsp页面传递过来是否分页 this.setPagination(req.getParameter("pagination")); // 保留上一次的查询请求 this.setUrl(req.getRequestURL().toString()); // 保留上一次的查询条件 this.setParameterMap(req.getParameterMap()); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map<String, String[]> getParameterMap() { return parameterMap; } public void setParameterMap(Map<String, String[]> parameterMap) { this.parameterMap = parameterMap; } private void setPagination(String pagination) { // 只有填写了false字符串,才代表不分页 this.setPagination(!"false".equals(pagination)); } private void setRows(String rows) { if (StringUtils.isNotBlank(rows)) this.setRows(Integer.valueOf(rows)); } private void setPage(String page) { if (StringUtils.isNotBlank(page)) this.setPage(Integer.valueOf(page)); } private boolean pagination = true;// 是否分页 public PageBean1() { super(); } 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; } public void setPagination(boolean pagination) { this.pagination = pagination; } /** * 获得起始记录的下标 * * @return */ public int getStartIndex() { return (this.page - 1) * this.rows; } @Override public String toString() { return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]"; } // 上一页 public int getPrevPage() { return this.page > 1 ? this.page - 1 : this.page; } // 下一页 public int getNextPage() { return this.page < this.getMaxPage() ? this.page + 1 : this.page; } // 最大页 public int getMaxPage() { return this.total % this.rows == 0 ? this.total / this.rows : (this.total / this.rows) + 1; } }
3.3自定义page描述文件
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>zking 1.1 core library</description> <display-name>zking core</display-name> <tlib-version>1.1</tlib-version> <short-name>zking</short-name> <uri>/zking</uri> <tag> <name>page</name> <tag-class>com.zking.tag.PageTag</tag-class> <body-content>JSP</body-content> <attribute> <name>pageBean</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
3.4page助手类
package com.xzs.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.xzs.util.PageBean; import com.xzs.util.PageBean1; public class PageTag extends BodyTagSupport { private PageBean1 pageBean; public PageBean1 getPageBean() { return pageBean; } public void setPageBean(PageBean1 pageBean) { this.pageBean = pageBean; } @Override public int doStartTag() throws JspException { JspWriter out = pageContext.getOut(); try { out.print(toHTML()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.doStartTag(); } private String toHTML() { StringBuffer sb = new StringBuffer(); // form sb.append("<form action=\""+pageBean.getUrl()+"\" id=\"pageBeanForm\" method=\"post\">"); sb.append(" <input type=\"hidden\" name=\"page\">"); Map<String, String[]> paramMap = pageBean.getParameterMap(); if(paramMap != null && paramMap.size() > 0) { Set<Entry<String, String[]>> entrySet = paramMap.entrySet(); for (Entry<String, String[]> entry : entrySet) { String name = entry.getKey(); String[] value = entry.getValue(); if(value != null && value.length > 0) { for (String val : value) { if(!"page".equals(entry.getKey())){ sb.append(" <input type=\"hidden\" name=\""+name+"\" value=\""+val+"\">"); } } } } } sb.append("</form>"); // 分页条 sb.append("<ul class=\"pagination justify-content-center\">"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == 1 ? "disabled" : "")+"\"><a class=\"page-link\""); sb.append(" href='javascript:gotoPage(1)'>首页</a></li>"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == 1 ? "disabled" : "")+"\"><a class=\"page-link\""); sb.append(" href='javascript:gotoPage("+pageBean.getPrevPage()+")'><</a></li>"); sb.append(" <li class=\"page-item\"><a class=\"page-link\" href=\"#\">"+pageBean.getPage()+"</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 "+(pageBean.getPage() == pageBean.getMaxPage() ? "disabled" : "")+"\"><a class=\"page-link\" href=\"javascript:gotoPage("+pageBean.getNextPage()+")\">></a></li>"); sb.append(" <li class=\"page-item "+(pageBean.getPage() == pageBean.getMaxPage() ? "disabled" : "")+"\"><a class=\"page-link\" href=\"javascript:gotoPage("+pageBean.getMaxPage()+")\">尾页</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>共"+pageBean.getTotal()+"条</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(); } }
3.5Bookservlet
package com.xzs.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.xzs.dao.BookDao1; import com.xzs.dao.Bookdao; import com.xzs.entity.Book; import com.xzs.util.PageBean; import com.xzs.util.PageBean1; @WebServlet("/book.search") public class BookServlet extends HttpServlet { @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 { BookDao1 bookdao = new BookDao1(); PageBean pageBean = new PageBean(); pageBean.setRequest(req); Book book = new Book(); book.setBname(req.getParameter("bname")); try { List<Book> list = bookdao.list(book, pageBean); req.setAttribute("books", list); req.setAttribute("pageBean", pageBean); req.getRequestDispatcher("/index.jsp").forward(req, resp); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3.6Jsp界面编写
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://tag.veryedu.cn" prefix="z" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script> <title>书籍列表</title> <style type="text/css"> .page-item input { padding: 0; width: 40px; height: 100%; text-align: center; margin: 0 6px; } .page-item input, .page-item b { line-height: 38px; float: left; font-weight: 400; } .page-item.go-input { margin: 0 10px; } </style> </head> <body> <form class="form-inline" action="${pageContext.request.contextPath }/book/search" method="post"> <div class="form-group mb-2"> <input type="text" class="form-control-plaintext" name="bname" placeholder="请输入书籍名称"> </div> <button type="submit" class="btn btn-primary mb-2">查询</button> </form> <table class="table table-striped bg-success"> <thead> <tr> <th scope="col">书籍ID</th> <th scope="col">书籍名</th> <th scope="col">价格</th> </tr> </thead> <tbody> <c:forEach items="${books }" var="b"> <tr> <td>${b.bid }</td> <td>${b.bname }</td> <td>${b.price }</td> </tr> </c:forEach> </tbody> </table> <z:page pageBean="${pageBean }"></z:page> </body> </html>
3.7测试结果
总结:通用分页就是方便我们简化代码的,所以我们需要将它们共同的代码进行差个分装。但在我们还不熟悉的时候应该先不考虑封装,先将分页写出来,然后提取公共构造,封装继承。通用分页步骤就是先分析分页条属性,然后封装属性实体,然后编写dao层方法提取公共部分,接着编写分页助手类,为了避免出现乱码问题,在编写一个字符过滤器,过滤所有请求,最后在标签库描述文件中添加分页标签,就可以按自己需求来使用了。通用分页的思想就是将能提取的部分给提取出来然后拼接,供以后调用。