阅读量:0
1.BookDao实现及测试
创建BookDao并定义实现书本查全部方法,最后完成Junit方法测试。
public class BookDao extends BaseDao<Book>{ /** * 添加 * @param book */ public void addBook(Book book){ Connection con = null; PreparedStatement ps = null; try{ //获取连接对象 con=DBHelper.getConnection(); ps=con.prepareStatement("insert into t_book values(?,?,?,?)"); ps.setString(1,book.getBookid()); ps.setString(2,book.getBookname()); ps.setFloat(3,book.getPrice()); ps.setString(4,book.getBooktype()); //执行SQL语句并返回影响行数 int i=ps.executeUpdate(); if(i<0) throw new Exception("执行失败,影响函数为0"); }catch (Exception e){ e.printStackTrace(); }finally { DBHelper.close(con,ps,null); } } /** * 模糊查询 * @param book * @return */ public List<Book> getByLike(Book book, PageBean pageBean) { String sql = "select * from t_book where 1=1"; if (StringUtils.isNotBlank(book.getBookname())) sql += " and bookname like '%" + book.getBookname() + "%'"; System.out.println(sql); return super.executeQuery(sql, pageBean, new CallBack<Book>() { @Override public List<Book> foreachRs(ResultSet rs) throws SQLException { return CommonUtils.toList(rs,Book.class); } }); } }
2.BookServlet实现及页面效果展示
创建BookServlet并调用BookDao中查全部方法实现书本查询。
public class BookServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取前端页面传入的查询条件 String bookname = req.getParameter("bookname"); //创建Book对象 Book book=new Book(); book.setBookname(bookname); //调用模糊查询方法 PageBean pageBean=new PageBean(); BookDao bookDao=new BookDao(); //获取前端传入的请求参数集 pageBean.setRequest(req); List<Book> books = bookDao.getByLike(book,pageBean); //将查询结果保存到request作用域中 req.setAttribute("books",books); //将pageBean保存到request作用域中 req.setAttribute("pageBean",pageBean); //转发 req.getRequestDispatcher("index.jsp").forward(req,resp); } }
1)打开web.xml,配置中文乱码过滤器EncodingFilter和书本查询Servlet控制器;
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--1、配置中文过滤器--> <filter> <filter-name>encodingFilter</filter-name> <filter-class>com.zking.pagintation.uitl.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--2、配置Servlet的servlet--> <servlet> <servlet-name>Servlet</servlet-name> <servlet-class>com.zking.pagintation.servlet.BookServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Servlet</servlet-name> <url-pattern>/Servlet.do</url-pattern> </servlet-mapping> <!--3、配置欢迎页--> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> </web-app>
2)创建BookServlet.jsp页面实现书本查询效果展示。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="z" uri="/zking" %> <html> <head> <title>通用分页</title> </head> <body> <h1>通用分页</h1> <form method="post" action="Servlet.do"> <label>书本名称:</label><input type="text" name="bookname"> <input type="submit" value="查询"> </form> <table width="100%" border="1" cellpadding="0" cellspacing="0"> <tr> <th>书本编号</th> <th>书本名称</th> <th>书本价格</th> <th>书本类型</th> </tr> <c:forEach var="b" items="${books}"> <tr> <td>${b.bookid}</td> <td>${b.bookname}</td> <td>${b.price}</td> <td>${b.booktype}</td> </tr> </c:forEach> </table> <z:pagination pageBean="${pageBean}"/> </body> </html>
3.通用分页实现
3.1.MySQL分页
limit语法
select * from table_name limit [offset,] rows
参数说明
参数 | 说明 |
---|---|
offset | 指定第一个返回记录行的偏移量(即从哪一行开始返回),注意:初始行的偏移量为0 |
rows | 返回具体行数 |
3.2.PageBean
创建PageBean分页标记类,用于定义分页相关要素。
/** * 分页工具类 */ public class PageBean { //当前页码 private int page=1; //每页条数 private int rows=10; //总机录数 private int total=0; //是否分页标记 private boolean pagination=true; //增强属性 //返回上一条请求的url路径 private String url; //获取上一次请求的所有请求参数集合 private Map<String,String[]> maps; public void setRequest(HttpServletRequest req){ //1、获取前端传入的分页三要素(page,rows,pagination) String page = req.getParameter("page"); String rows = req.getParameter("rows"); String pagination = req.getParameter("pagination"); this.setPage(page); this.setRows(rows); this.setPagination(pagination); //2、获取上一次请求的URL路径 //req.getContextPath == 获取项目名 //req.getServletPath() == 获取servlet请求路径名 //req.getRequestURL == req.getContextPath+req.getServletPath() this.url=req.getRequestURI(); //3、获取上一次请求的所有请求参数集合 this.maps = req.getParameterMap(); } /** * 返回limit分页查询的开始位置 * @return */ public int getStartIndex(){ return (this.page-1)*this.rows; } //重载set方法 public void setPage(String page) { if(null!=page) this.page = Integer.parseInt(page); } public void setRows(String rows) { if(null!=rows) this.rows = Integer.parseInt(rows); } public void setPagination(String pagination) { if(null!=pagination) this.pagination = Boolean.parseBoolean(pagination); } /** * //分页方法 * //计算总分页 * @return 总分页数 */ public int getMaxPager(){ int max = this.total/this.rows; //除不尽有余数 if(this.total%this.rows!=0) max++; return max; } /** * 上一页方法 * @return 上一页页数 */ public int getPrevPager(){ int prev = this.page-1; if(prev<=1) prev=1; return prev; } /** * 下一页方法 * @return 下一页页数 */ public int getNextPager(){ int next=this.page+1; if(next>=getMaxPager()) next=getMaxPager(); return next; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map<String, String[]> getMaps() { return maps; } public void setMaps(Map<String, String[]> maps) { this.maps = maps; } 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 boolean isPagination() { return pagination; } public void setPagination(boolean pagination) { this.pagination = pagination; } @Override public String toString() { return "PageBean{" + "page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + ", url='" + url + '\'' + ", maps=" + maps + '}'; } }
3.3.BaseDao
创建BaseDao通用分页类并定义相关分页方法。
3.3.1分页查询方法
public class BaseDao<T> { /** * 通用分页方法 (分页或不分页) * @param sql 普通SQL语句 * @param pageBean 分页标记对象 * @return 返回分页结果集 */ public List<T> executeQuery(String sql, PageBean pageBean,CallBack<T> callBack){ Connection con=null; PreparedStatement ps=null; ResultSet rs=null; try{ con= DBHelper.getConnection(); if(null!=pageBean&&pageBean.isPagination()){ //分页 //1)根据满足的条件查询分页总记录数 String countSQL = this.getCountSQL(sql); ps=con.prepareStatement(countSQL); rs=ps.executeQuery(); if(rs.next()){ int total = rs.getInt(1); //将查询得到的总记录数存入Page Bean对象中的total属性 pageBean.setTotal(total); } //2)根据满足的条件查询分页结果集 sql = this.getPagerSQL(sql, pageBean); } ps=con.prepareStatement(sql); rs=ps.executeQuery(); return callBack.foreachRs(rs); }catch (Exception e){ e.printStackTrace(); }finally { DBHelper.close(con,ps,rs); } return null; } }
在executeQuery方法中根据PageBean对象及对象属性pagination识别是否分页。
分页:查询分页结果、集查询总记录数
将普通的SQL语句转换成分页查询的SQL语句
/** * 将普通的SQL语句转换成分页查询的SQL语句 * @param sql 普通SQL语句 * @param pageBean 分页标记对象 * @return 分页查询的SQL语句 */ private String getPagerSQL(String sql,PageBean pageBean){ return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows(); }
- 将普通sql语句转换成查总记录数的sql
/** * 将普通sql语句转换成查总记录数的sql * @param sql * @return 查询总记录数的SQL语句 */ private String getCountSQL(String sql){ return "select count(*) from ("+sql+") temp"; }
不分页:只查询数据结果集(不查询分页记录和总记录数)
3.3.2.匿名内部接口
在BaseDao类中定义匿名内部接口,该接口中的forEach方法只用于循环遍历ResultSet查询结果集并返回List<T>
/** * 用于遍历结果集数据的回调接口 * @author Administrator * @param <T> */ public static interface CallBack<T>{ public List<T> foreachRs(ResultSet rs) throws SQLException; }
修改executeQuery方法,将匿名内部接口CallBack当做入参传入方法中。
public List<T> executeQuery(String sql, PageBean pageBean,CallBack<T> callBack){ Connection con=null; PreparedStatement ps=null; ResultSet rs=null; try{ con= DBHelper.getConnection(); if(null!=pageBean&&pageBean.isPagination()){ //分页 //1)根据满足的条件查询分页总记录数 String countSQL = this.getCountSQL(sql); ps=con.prepareStatement(countSQL); rs=ps.executeQuery(); if(rs.next()){ int total = rs.getInt(1); //将查询得到的总记录数存入Page Bean对象中的total属性 pageBean.setTotal(total); } //2)根据满足的条件查询分页结果集 sql = this.getPagerSQL(sql, pageBean); } ps=con.prepareStatement(sql); rs=ps.executeQuery(); return callBack.foreachRs(rs); }catch (Exception e){ e.printStackTrace(); }finally { DBHelper.close(con,ps,rs); } return null; }
3.3.3.Junit单元测试
Junit是一个Java测试框架,使编写可靠和高效的测试变得容易。它可以用于大多数语言制作的应用程序,但特别适合于测试Java应用程序。Junit也可以用来创建自动测试。
Junit框架是最流行的Java测试框架之一。它提供了一些功能,使编写测试变得容易,包括支持多个测试用例、断言和报告。Junit也是多功能的,允许用各种语言编写测试。
setUp():在方法之前执行
tearDown:在方法之后执行
public class BookDaoTest { @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testQueryBookPager() { fail("Not yet implemented"); } }
Junit中的setUp和tearDown方法是根据方法数量来决定的
4.增强PageBean
package com.zking.pagintation.uitl; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * 分页工具类 */ public class PageBean { //当前页码 private int page=1; //每页条数 private int rows=10; //总机录数 private int total=0; //是否分页标记 private boolean pagination=true; //增强属性 //返回上一条请求的url路径 private String url; //获取上一次请求的所有请求参数集合 private Map<String,String[]> maps; public void setRequest(HttpServletRequest req){ //1、获取前端传入的分页三要素(page,rows,pagination) String page = req.getParameter("page"); String rows = req.getParameter("rows"); String pagination = req.getParameter("pagination"); this.setPage(page); this.setRows(rows); this.setPagination(pagination); //2、获取上一次请求的URL路径 //req.getContextPath == 获取项目名 //req.getServletPath() == 获取servlet请求路径名 //req.getRequestURL == req.getContextPath+req.getServletPath() this.url=req.getRequestURI(); //3、获取上一次请求的所有请求参数集合 this.maps = req.getParameterMap(); } /** * 返回limit分页查询的开始位置 * @return */ public int getStartIndex(){ return (this.page-1)*this.rows; } //重载set方法 public void setPage(String page) { if(null!=page) this.page = Integer.parseInt(page); } public void setRows(String rows) { if(null!=rows) this.rows = Integer.parseInt(rows); } public void setPagination(String pagination) { if(null!=pagination) this.pagination = Boolean.parseBoolean(pagination); } /** * //分页方法 * //计算总分页 * @return 总分页数 */ public int getMaxPager(){ int max = this.total/this.rows; //除不尽有余数 if(this.total%this.rows!=0) max++; return max; } /** * 上一页方法 * @return 上一页页数 */ public int getPrevPager(){ int prev = this.page-1; if(prev<=1) prev=1; return prev; } /** * 下一页方法 * @return 下一页页数 */ public int getNextPager(){ int next=this.page+1; if(next>=getMaxPager()) next=getMaxPager(); return next; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map<String, String[]> getMaps() { return maps; } public void setMaps(Map<String, String[]> maps) { this.maps = maps; } 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 boolean isPagination() { return pagination; } public void setPagination(boolean pagination) { this.pagination = pagination; } @Override public String toString() { return "PageBean{" + "page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + ", url='" + url + '\'' + ", maps=" + maps + '}'; } }
5.创建自定义分页标签
5.1.创建自定义分页标签助手类
package com.zking.pagintation.tag; import com.zking.pagintation.uitl.PageBean; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; import java.util.Map; import java.util.Set; public class PaginationTag extends BodyTagSupport { private PageBean pageBean; public PageBean getPageBean() { return pageBean; } public void setPageBean(PageBean pageBean) { this.pageBean = pageBean; } @Override public int doStartTag() throws JspException { try{ JspWriter out = pageContext.getOut(); out.print(toHtml()); }catch (Exception e){ e.printStackTrace(); } return SKIP_BODY; } private String toHtml(){ //判断PageBean是否为空 if(null!=pageBean&&pageBean.isPagination()){ //定义StringBuffer可变字符串 //面试题:String/StringBuffer/StringBuilder/的区别 StringBuffer sb=new StringBuffer(); //拼接div跟标签 sb.append("<div style=\"float: right;\">"); //拼接form标签对象 sb.append("<form id=\"pageForm\" method=\"post\" action="+pageBean.getUrl()+">"); //拼接page隐藏域 sb.append(" <input type=\"hidden\" name=\"page\"/>"); //获取请求参数集合 Map<String,String[]> maps=pageBean.getMaps(); //获取请求参数集合的键值对 Set<Map.Entry<String, String[]>> entries = maps.entrySet(); //循环遍历请求参数键值对 for (Map.Entry<String, String[]> entry : entries) { //判断请求参数是否是page,如果是 则continue if(entry.getKey().equalsIgnoreCase("page")) continue; //获取请求参数的value值(类型为String[]) String[] values = entry.getValue(); //循环遍历value值 for(String value : values){ sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+value+"'>"); } } sb.append("</form>"); //拼接分页信息 sb.append("第"+pageBean.getPage()+"页/总"+pageBean.getMaxPager()+"页数"); //拼接首页、上一页、下一页、末页 if(pageBean.getPage()==1) sb.append("首页 上一页"); else { sb.append("<a onclick=\"gotoPage(1)\" href=\"javascript:void(0);\">首页</a>"); sb.append("<a onclick=\"gotoPage("+pageBean.getPrevPager()+")\" href=\"javascript:void(0);\">上一页</a>"); } if(pageBean.getPage()==pageBean.getMaxPager()) sb.append("下一页 末页"); else { sb.append("<a onclick=\"gotoPage("+pageBean.getNextPager()+")\" href=\"javascript:void(0);\">下一页</a>"); sb.append("<a onclick=\"gotoPage("+pageBean.getMaxPager()+")\" href=\"javascript:void(0);\">末页</a>"); } //拼接javascpit sb.append("<script>\n" + " function gotoPage(page){\n" + " document.getElementById('pageForm').page.value=page;\n" + " document.getElementById('pageForm').submit();\n" + " }\n" + "</script>"); sb.append("</div>"); return sb.toString(); } return ""; } @Override public int doEndTag() throws JspException { return EVAL_PAGE; } }
5.2.导入标签描述文件
详见课件"z.tld"文件