JSP通用分页框架

SimaDouglas 8年前

来自: http://blog.csdn.net/u012706811/article/details/50685355


写一个通用的分页框架,这样一个项目里面如果想做分页,只需要改动少数参数就可以实现分页处理了,这样写起来会简单很多


一.分页类

既然要分页那么我们就要考虑建一个通用的分页类,里面需要的参数一般有:

  • 总页数 totalPage
  • 总共记录数 totalRecord
  • 每页显示数 pageSize
  • 当前页pageIndex
  • 承载当前页数据的集合 List datas
    完整代码:Page.java
  • import java.util.List;    public class Pager<E> {      /** * 总共页数 */      private int totalPages;      /** * 总共记录数 */      private int totalRecords;      /** * 每页显示数量 */      private int pageSize;      /** * 当前页 */      private int pageIndex;      /** * 当前页数据集合 */      private List<E> datas;        public void setTotalPages(int totalPages) {          this.totalPages = totalPages;      }        public void setTotalRecords(int totalRecords) {          this.totalRecords = totalRecords;      }        public void setPageSize(int pageSize) {          this.pageSize = pageSize;      }        public void setPageIndex(int pageIndex) {          this.pageIndex = pageIndex;      }        public void setDatas(List<E> datas) {          this.datas = datas;      }        public int getTotalPages() {          return totalPages;      }        public int getTotalRecords() {          return totalRecords;      }        public int getPageSize() {          return pageSize;      }        public int getPageIndex() {          return pageIndex;      }        public List<E> getDatas() {          return datas;      }  }

    二.用户类

    这里以查询用户来做分页为例,所以就需要一个用户类

  • 用户号 userId
  • 用户姓名 username
  • 用户密码 password
  • 注册时间 regdate
    完整代码
  • import java.sql.Timestamp;    public class User {      private int userId;//用户id      private String username;//用户名      private String password;//密码      private Timestamp regdate;//注册时间        public int getUserId() {          return userId;      }        public void setUserId(int userId) {          this.userId = userId;      }        public String getUsername() {          return username;      }        public void setUsername(String username) {          this.username = username;      }        public String getPassword() {          return password;      }        public void setPassword(String password) {          this.password = password;      }        public Timestamp getRegdate() {          return regdate;      }        public void setRegdate(Timestamp regdate) {          this.regdate = regdate;      }  }

    三.threadLocal提取公用参数

    先说如果不提取公共参数,比如pagesize,pageindex,那么我们的查询方法应该是这样子:

       public void GetUsers(String name,int pagesize,int pageIndex)

    如果以后再增加参数,无疑这里的参数会变的很多,所以我们利用threadLocal把pagesize和pageindex提取出来.

    先写这个类

    public class SystemContext {      //页大小      private static ThreadLocal<Integer> pageSize = new ThreadLocal<>();      //当前页      private static ThreadLocal<Integer> pageIndex = new ThreadLocal<>();        public static Integer getPageSize() {          return pageSize.get();      }      public static void removePageSize(){          pageSize.remove();      }      public static void setPageSize(int _pageSize) {          pageSize.set(_pageSize);      }        public Integer getPageIndex() {          return pageIndex.get();      }        public void setPageIndex(int _pageIndex) {          pageIndex.set(_pageIndex);      }      public static void removePageIndex(){          pageIndex.remove();      }  }

    对于threadLocal,这个变量会在线程中一直存在,那么我们就可以在向服务器发送请求的时候添加参数,服务器返回数据的时候移除参数,一来一回的话,自然而然可以用过滤器
    那么过滤器如下:

    import com.dao.SystemContext;    import javax.servlet.*;  import java.io.IOException;    public class SystemFilter implements Filter{      int pageSize;      int pageIndex = 1;      @Override      public void init(FilterConfig filterConfig) throws ServletException {          try {              pageSize = Integer.parseInt(filterConfig.getInitParameter("pagesize"));          } catch (NumberFormatException e) {              pageSize = 15;          }      }        @Override      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {            try {              pageIndex = Integer.parseInt(servletRequest.getParameter("pageindex"));          }catch (NumberFormatException e){              //什么也不做,pageindex=1          }          try {              //开始请求的时候配置参数              SystemContext.setPageSize(pageSize);              SystemContext.setPageIndex(pageIndex);              filterChain.doFilter(servletRequest,servletResponse);          }finally {              //请求返回的时候移除参数              SystemContext.removePageIndex();              SystemContext.removePageSize();          }          }        @Override      public void destroy() {        }  }

    用了过滤器,自然要在web.xml中配置过滤器

    <?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_3_1.xsd" version="3.1">        <filter>          <filter-name>SystemFilter</filter-name>          <filter-class>com.filter.SystemFilter</filter-class>          <!--配置没页大小-->          <init-param>              <param-name>pagesize</param-name>              <param-value>15</param-value>          </init-param>      </filter>      <filter-mapping>          <filter-name>SystemFilter</filter-name>          <!--这里配置需要分页的页面-->          <url-pattern>/index.jsp</url-pattern>        </filter-mapping>  </web-app>

    这样的好处不言而喻,结构清晰,修改方便.接下来是分页代码

    四.分页代码

    分页代码应该写一个接口和实现类的,这里演示项目就写在了一起

    import com.util.Pager;  import com.util.User;    import java.sql.*;  import java.util.ArrayList;  import java.util.List;    public class UserDAO {        private Connection conn = null;      private ResultSet rs = null;      private PreparedStatement ps = null;    // public static void main(String[] args) {  // UserDAO dao = new UserDAO();  // dao.GetUsers("",15,1);  // dao.close();  // }        public UserDAO() {          String driverName = "com.mysql.jdbc.Driver";          String url = "jdbc:mysql://localhost:3306/fenyedemo";          String user = "root";String password = "123456";          try {              Class.forName(driverName);              conn = DriverManager.getConnection(url,user,password);          } catch (ClassNotFoundException e) {              System.out.println("没有发现驱动");              e.printStackTrace();          } catch (SQLException e) {              System.out.println("获取连接失败");              e.printStackTrace();          }      }      /** * 具体分页实现代码 * @param name 查询条件 * @return */      public Pager GetUsers(String name){          //获取分页参数          int pagesize = SystemContext.getPageSize();          int pageIndex = SystemContext.getPageIndex();          //分页具体sql语句          String sql = "select * from user ";          String sqlCount = "select count(*) from user ";          if (name!=null && !name.trim().equals("")){              sql += "where username LIKE %"+name+"%";              sqlCount += "where username LIKE %"+name+"%";          }          sql += " LIMIT ?,?";          //存放当前页的集合          List<User> datas = new ArrayList<>();          //存放当前分页的集合          Pager<User> pages = new Pager<>();          User userTemp = null;          try {              ps = conn.prepareStatement(sql);              if(pageIndex<=0) pageIndex=1;              //设置参数              ps.setInt(1,(pageIndex-1)*pagesize);              ps.setInt(2,pagesize);              rs = ps.executeQuery();              //循环取出,添加到datas中              while (rs.next()){                  userTemp = new User();                  userTemp.setUserId(rs.getString("id"));                  userTemp.setUsername(rs.getString("username"));                  userTemp.setPassword(rs.getString("password"));                  userTemp.setRegdate(rs.getTimestamp("regdate"));                  datas.add(userTemp);              }              //最后设置pages              pages.setPageIndex(pageIndex);              pages.setPageSize(pagesize);              ps = conn.prepareStatement(sqlCount);              rs = ps.executeQuery();              while(rs.next()){                  pages.setTotalRecords(rs.getInt(1));                  pages.setTotalPages((rs.getInt(1)-1)/pagesize+1);              }              pages.setDatas(datas);          } catch (SQLException e) {              System.out.println("获取出错");              e.printStackTrace();          }            return pages;        }          public void close(){           try {               if (rs!=null) rs.close(); rs = null;               if (ps!=null) ps.close(); ps = null;               if (conn!=null) conn.close(); conn = null;          } catch (SQLException e) {               System.out.println("关闭失败");              e.printStackTrace();          }      }  }

    五.jsp测试页面

    普通页面就是显示数据,这个很简单,代码如下

    <%@ page import="com.dao.UserDAO" %>  <%@ page import="com.util.Pager" %>  <%@ page import="com.util.User" %>  <%@ page import="java.util.Iterator" %>  <%@ page contentType="text/html;charset=UTF-8" language="java" %>  <% String condition = request.getParameter("condition"); UserDAO userDAO = new UserDAO(); Pager<User> pages = null; if (condition!=null && !condition.trim().equals("")){ pages = userDAO.GetUsers(condition); }else { pages = userDAO.GetUsers(null); } userDAO.close(); %>  <html>  <head>      <title>测试用例</title>  </head>  <body>  <h1 align="center">分页测试</h1>  <table align="center" border="1" width="700">      <tr>          <td colspan="100%">              <form method="get" action="index.jsp">                  <input type="text" name="condition">                  <input type="submit" value="查询">              </form>          </td>      </tr>      <tr>          <th>ID</th>          <th>USERNAME</th>          <th>PASSWORD</th>          <th>DATA</th>      </tr>      <% for (Iterator it = pages.getDatas().iterator(); it.hasNext() ; ) { User userTemp = (User) it.next(); %>      <tr>          <td><%=userTemp.getUserId()%></td>          <td><%=userTemp.getUsername()%></td>          <td><%=userTemp.getPassword()%></td>          <td><%=userTemp.getRegdate()%></td>      </tr>      <% }%>  </table>  </body>  </html>

    此时已经有一些效果了
    这里写图片描述

    六.JSP页面添加控制选项

    添加控制选项这里使用分页框架pager-taglib,也是为了更好的支持通用性.
    首先在index.jsp页面查询之后静态引入一个新的页面,作为底部控制页面

    使用方法,就是去下载相应的jar,然后引入到项目的lib中即可
    这里写图片描述

     <tr><td colspan="100%">          <jsp:include page="fenye.jsp">              <jsp:param name="items" value="<%=pages.getTotalRecords()%>"/>              <jsp:param name="maxPageItems" value="<%=pages.getPageSize()%>"/>              <jsp:param name="maxIndexPages" value="10"/>              <jsp:param name="params" value="condition"/>          </jsp:include>      </td></tr>

    下面开始写fenye.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>  <% int items = Integer.parseInt(request.getParameter("items")); int maxPageItems = Integer.parseInt(request.getParameter("maxPageItems")); int maxIndexPages = Integer.parseInt(request.getParameter("maxIndexPages")); String params = request.getParameter("params"); %>  <%--引入分页框架--%>  <%@taglib prefix="pg" uri="http://jsptags.com/tags/navigation/pager" %>  <%--参数依次是项目总数 每页显示数量 下方菜单显示数 当前页curPage--%>  <pg:pager items="<%=items%>" maxPageItems="<%=maxPageItems%>" maxIndexPages="<%=maxIndexPages%>" export="curPage=pageNumber">      <pg:param name="<%=params%>"/>      <pg:first>          <a href="<%=pageUrl%>">首页</a>      </pg:first>      <pg:prev>          <a href="<%=pageUrl%>">上一页</a>      </pg:prev>      <pg:pages>          <% if(curPage==pageNumber) { %>          [<%=pageNumber %>]          <% } else { %>          <a href="<%=pageUrl%>"><%=pageNumber %></a>          <% } %>        </pg:pages>      <pg:next>          <a href="<%=pageUrl %>">下一页</a>      </pg:next>      <pg:last>          <a href="<%=pageUrl %>">尾页</a>      </pg:last>  </pg:pager>

    分页设计基本就是上面框架,重点是参数传递,这里参数传递利用静态引入的时候,配置jsp:param,然后到fenye,jsp中再取出.
    其中pager-taglib中有一个标签是”/>,这个就是针对我的查询条件传递过来的参数,如果没传递,那么查询的话点击下一页也会出错,这里还有一个问题就是编码问题,pager-taglib默认编码是GB2312,你可以重新打包文件编译,也可以在tomcat的server.xml文件中配置urlEncording=”utf-8”,这样就会没问题了.
    这里写图片描述

    七.总结

    这样的一个框架,如果其他需要实现分页的就可以直接套用了,建立相应的实体类,写好分页代码,直接套用Systemcontex.java和SystemFilter.java(记得在web.xml配置相应的过滤文件),再jsp中可以直接使用fenye.jsp,这样就会省下很多麻烦