web分页
为什么需要分页?
一、数据方面的原因
大量查询的数据耗时比较严重。
二、增强用户使用体验需求
用户更方便的查询和展示他所需要的数据。
常见分页方式:传统分页方式和下拉式分页方式。
采用传统的分页方式,可以明确的获取数据信息,如有多少条数据,分多少页显示。
采用下拉式分页方式,一般无法获取明确的数据数量相关的信息,但是在分页操作以后,仍然可以看到之前查询的数据。
常见的分页实现方式
1. 使用subList()实现分页。
List<E> subList(int fromIndex,int toIndex)
返回列表中指定的fromIndex(包含)和 toIndex (不包括)之间的部分视图。
2. 使用SQL语句实现分页
利用数据库自带的分页语法,使用分页语句,获取分页数据(例如mysql数据库使用limit关键字,oracle中使用rownum关键字等)
Mysql
- select * from students limit0,10 从第0条开始查,一共查询10条记录。
3. 使用hibernate框架进行分页。
创建Query或者Criteria对象,查询时,设置firstResult(从第几条开始查)和maxResults(查询几条记录)属性。
String hql = “ from Student”; Query q = session.createQuery(hql); q.setFirstResult(0); q.setMaxResults(10); List l = q.list(); |
实现方式 | 优点 | 缺点 | 使用场景 |
subList | 简单、易用 | 效率低 | 无法按需批量获取数据 |
SQL语句 | 简单、直接、效率高 | 数据库兼容性差 | 不要求数据库兼容 |
Hibernate框架 | 面向对象,兼容性强 | 复杂查询性能低 | 兼容不同数据库 |
1. 使用sublist实现分页。
创建model层
学生对象 Student类
- public class Student implements Serializable{
- /**
- *
- */
- private static final long serialVersionUID = -2448260736229612919L;//序列化id
- private int id;//学生记录的id
- private String stuName;//姓名
- private int age;//年龄
- private int gender;//性别
- private String address;//地址
- public Student(){
- super();
- }
- public Student(int id, String stuName, int age, int gender, String address) {
- super();
- this.id = id;
- this.stuName = stuName;
- this.age = age;
- this.gender = gender;
- this.address = address;
- }
- /*
- * 构造函数,将查询到的Map类型的数据构造成学生对象
- */
- public Student(Map<String,Object> map){
- this.id = (int)map.get("id");
- this.stuName = (String)map.get("stu_name");
- this.age = (int)map.get("age");
- this.gender = (int)map.get("gender");
- this.address = (String)map.get("address");
- }
- }
- public class Pager<T> implements Serializable{
- /**
- * 序列化id
- */
- private static final long serialVersionUID = 7569566861340703188L;
- private int pageSize;//每页显示多少条记录
- private int currentPage;//当前第几页数据
- private int totalRecord;//一共多少条记录
- private List<T> dataList;//要显示的数据
- private int totalPage;//总页数
- public Pager() {
- super();
- }
- public Pager(int pageSize, int currentPage, int totalRecord,
- int totalPage,List<T> dataList) {
- super();
- this.pageSize = pageSize;
- this.currentPage = currentPage;
- this.totalRecord = totalRecord;
- this.totalPage = totalPage;
- this.dataList = dataList;
- }
- public Pager(int pageNum,int pageSize,List<T> sourceList){
- if(sourceList.size() ==0 ||sourceList == null){
- return;
- }
- //总记录条数
- this.totalRecord = sourceList.size();
- //每页显示多少条记录
- this.pageSize = pageSize;
- //获取总页数
- this.totalPage = this.totalRecord /this.pageSize;
- if(this.totalRecord % this.pageSize != 0){
- this.totalPage = this.totalPage +1;
- }
- //当前第几页数据
- if(this.totalPage < pageNum){
- this.currentPage = this.totalPage;
- }else{
- this.currentPage = pageNum;
- }
- //起始索引
- int fromIndex = this.pageSize*(this.currentPage-1);
- //结束索引
- int toIndex;
- if(this.pageSize * this.currentPage >this.totalRecord){
- toIndex = this.totalRecord;
- }else{
- toIndex = this.pageSize * this.currentPage;
- }
- this.dataList = sourceList.subList(fromIndex, toIndex);
- }
- }
- public class JdbcUtil {
- //表示定义数据库的用户名
- private static String USERNAME;
- //定义数据库的密码
- private static String PASSWORD;
- //定义数据库的驱动信息
- private static String DRIVER;
- //定义访问数据库的地址
- private static String URL;
- //定义数据库的连接
- private Connection connection;
- //定义sql语句的执行对象
- private PreparedStatement pstmt;
- //定义查询返回的结果集合
- private ResultSet resultSet;
- static{
- loadConfig();
- }
- /**
- * 加载数据库配置文件,并给相关的属性赋值,配置信息写在配置文件中,方便管理
- */
- public static void loadConfig(){
- //路径 WEB-INF\classes\jdbc.properties
- InputStream inStream = JdbcUtil.class.getResourceAsStream("/jdbc.properties");
- Properties prop = new Properties();
- try{
- prop.load(inStream);
- USERNAME = prop.getProperty("jdbc.username");
- PASSWORD = prop.getProperty("jdbc.password");
- DRIVER= prop.getProperty("jdbc.driver");
- URL = prop.getProperty("jdbc.url");
- }catch(Exception e){
- throw new RuntimeException("读取用户配置文件出错",e);
- }
- }
- /**
- * 获取数据库连接
- */
- public Connection getConnection(){
- try {
- Class.forName(DRIVER);//注册驱动
- //获取连接对象
- connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return connection;
- }
- /**
- * 执行更新操作
- * sql sql语句
- * params 执行参数
- * return 执行结果
- */
- public boolean updateByPreparedStatement(String sql,List<?> params)throws SQLException{
- boolean flag = false;
- int result = -1;//表示用户执行添加删除和修改的时候所影响数据库的行数
- pstmt = connection.prepareStatement(sql);
- int index = 1;
- //填充sql语句中的占位符
- if(params != null && !params.isEmpty()){
- for(int i=0;i < params.size();i++){
- pstmt.setObject(index ++, params.get(i));
- }
- }
- result = pstmt.executeUpdate();
- flag = result >0 ? true : false;
- return flag;
- }
- /**
- * 执行查询操作
- * sql sql语句
- * params 执行参数
- */
- public List<Map<String, Object>> findResult(String sql,List<?> params)throws SQLException{
- List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
- int index = 1;
- pstmt = connection.prepareStatement(sql);
- /*
- * 填充查询语句的参数
- */
- if(params != null && !params.isEmpty()){
- for(int i = 0;i<params.size();i++){
- pstmt.setObject(index ++, params.get(i));
- }
- }
- resultSet = pstmt.executeQuery();
- /*
- * 通过ResultSetMetaData获取一个ResultSet的列的类型和关于列的属性信息,如列名、列数等
- */
- ResultSetMetaData metaData = resultSet.getMetaData();
- //获取列的数量
- int cols_len = metaData.getColumnCount();
- /*
- * 遍历resultSet
- */
- while(resultSet.next()){
- Map<String,Object> map = new HashMap<String, Object>();
- for(int i= 0;i<cols_len;i++){
- //获取列名
- String cols_name = metaData.getColumnName(i+1);
- //根据列名获取列值
- Object cols_value = resultSet.getObject(cols_name);
- if(cols_value == null){
- cols_value ="";
- }
- map.put(cols_name, cols_value);
- }
- list.add(map);
- }
- return list;
- }
- /**
- * 释放资源
- *
- */
- public void releaseConn(){
- if(resultSet != null){
- try {
- resultSet.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- if(pstmt != null){
- try {
- pstmt.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- if(connection != null){
- try {
- connection.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
- jdbc.username=root
- jdbc.password=limeng
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc\:mysql\://127.0.0.1\:3306/pager
创建Dao层,数据操作对象
接口 StudentDao.java
- public interface StudentDao {
- /**
- * 根据查询条件,查询学生分页信息
- * @param searchModel 封装查询条件
- * @param pageNum 查询第几条数据
- * @param pageSize 显示多少数据
- * @return
- */
- public Pager<Student> findStudent(Student searchModel,int pageNum,int pageSize);
- }
- public class SublistStudentDaoImpl implements StudentDao{
- @Override
- public Pager<Student> findStudent(Student searchModel, int pageNum,
- int pageSize) {
- /*
- * 根据条件获取所有数据
- */
- List<Student> allStudentList = getAllStudent(searchModel);
- /*
- * 根据参数创建分页对象
- */
- Pager<Student> pager = new Pager<Student>(pageNum,pageSize,allStudentList);
- return pager;
- }
- /*
- * 获取所有数据
- */
- private List<Student> getAllStudent(Student searchModel){
- List<Student> result = new ArrayList<Student>();
- List<Object> paramList = new ArrayList<Object>();
- String stuName = searchModel.getStuName();
- int gender = searchModel.getGender();
- StringBuilder sql = new StringBuilder("select * from t_student where 1=1");
- if(stuName != null && !stuName.equals("")){
- sql.append(" and stu_name like ?");
- paramList.add("%"+stuName+"%");
- }
- if(gender == Constant.GENDER_FEMALE || gender== Constant.GENDER_MALE){
- sql.append(" and gender = ?");
- paramList.add(gender);
- }
- JdbcUtil jdbcUtil = null;
- try {
- jdbcUtil = new JdbcUtil();
- jdbcUtil.getConnection();
- List<Map<String, Object>> mapList = jdbcUtil.findResult(sql.toString(), paramList);
- if(mapList != null){
- for(Map<String, Object> map : mapList){
- Student s = new Student(map);
- result.add(s);
- }
- }
- } catch (SQLException e) {
- throw new RuntimeException("查询所有数据异常!",e);
- }finally{
- if(jdbcUtil != null){
- jdbcUtil.releaseConn();
- }
- }
- return result;
- }
- }
- public class SublistStudentServiceImpl implements StudentService{
- private StudentDao studentDao;
- public SublistStudentServiceImpl(){
- //创建service实现类时,初始化dao对象
- studentDao = new SublistStudentDaoImpl();
- }
- @Override
- public Pager<Student> findStudent(Student searchModel, int pageNum,
- int pageSize) {
- Pager<Student> result = studentDao.findStudent(searchModel, pageNum, pageSize);
- return result;
- }
- public StudentDao getStudentDao() {
- return studentDao;
- }
- public void setStudentDao(StudentDao studentDao) {
- this.studentDao = studentDao;
- }
- }
- public class SublistServlet extends HttpServlet {
- //创建service对象
- private StudentService studentService = new SublistStudentServiceImpl();
- public SublistServlet() {
- super();
- }
- public void destroy() {
- super.destroy(); // Just puts "destroy" string in log
- // Put your code here
- }
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- /*
- * 设置编码格式,防止解析中文参数乱码
- */
- request.setCharacterEncoding("utf-8");
- /* 接收request参数
- * 学生姓名
- */
- String stuName = request.getParameter("stuName");
- /*
- * 性别,默认是0,表示全部,不论男女
- */
- int gender = Constant.DEFAULT_GENDER;
- String genderStr = request.getParameter("gender");
- if(genderStr != null && !"".equals(genderStr.trim())){
- gender = Integer.parseInt(genderStr);// 获取学生性别
- }
- /*
- * 当前请求第几页
- */
- int pageNum = Constant.DEFAULT_PAGENUM;
- String pageNumStr = request.getParameter("pageNum");
- //参数校验,是否是数字
- if(pageNumStr != null && !StringUtil.isNum(pageNumStr)){
- request.setAttribute("errorMsg", "参数输入错误");
- request.getRequestDispatcher("sublistStudent.jsp").forward(request,
- response);
- return;
- }
- if(pageNumStr != null && !"".equals(pageNumStr.trim())){
- pageNum = Integer.parseInt(pageNumStr);//获取当前请求第几页
- }
- /*
- * 每页显示多少条数据
- */
- int pageSize = Constant.DEFAULT_PAGE_SIZE;
- String pageSizeStr = request.getParameter("pageSize");
- if(pageSizeStr != null && !"".equals(pageSizeStr.trim())){
- pageSize = Integer.parseInt(pageSizeStr);// 每页显示多少条记录
- }
- // 组装查询条件
- Student searchModel = new Student();
- searchModel.setStuName(stuName);
- searchModel.setGender(gender);
- // 调用service查询结果
- Pager<Student> result = studentService.findStudent(searchModel,
- pageNum, pageSize);
- // 返回结果到页面
- request.setAttribute("result", result);
- request.getRequestDispatcher("sublistStudent.jsp").forward(request,
- response);
- }
- }
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>学生信息</title>
- </head>
- <%
- // 获取请求的上下文
- String context = request.getContextPath();
- %>
- <script type="text/javascript">
- // 当前第几页数据
- var currentPage = ${result.currentPage};
- // 总页数
- var totalPage = ${result.totalPage};
- function submitForm(actionUrl){
- var formElement = document.getElementById("stuForm");
- formElement.action = actionUrl;
- formElement.submit();
- }
- // 第一页
- function firstPage(){
- if(currentPage == 1){
- alert("已经是第一页数据");
- return false;
- }else{
- submitForm("<%=context %>/sublist/SublistServlet?pageNum=1");
- return true;
- }
- }
- // 下一页
- function nextPage(){
- if(currentPage == totalPage){
- alert("已经是最后一页数据");
- return false;
- }else{
- submitForm("<%=context %>/sublist/SublistServlet?pageNum=" + (currentPage+1));
- return true;
- }
- }
- // 上一页
- function previousPage(){
- if(currentPage == 1){
- alert("已经是第一页数据");
- return false;
- }else{
- submitForm("<%=context %>/sublist/SublistServlet?pageNum=" + (currentPage-1));
- return true;
- }
- }
- // 尾页
- function lastPage(){
- if(currentPage == totalPage){
- alert("已经是最后一页数据");
- return false;
- }else{
- submitForm("<%=context %>/sublist/SublistServlet?pageNum=${result.totalPage}");
- return true;
- }
- }
- /*
- * 在初次加载时默认选择全部
- */
- function initPage(){
- var genderRequest = "${gender}" ;
- var genderVal = 0;
- var genderElement = document.getElementById("gender");
- if(genderRequest != ""){
- genderVal = parseInt(genderRequest);
- }
- var options = genderElement.options;
- var i = 0;
- for(i = 0; i < options.length; i++){
- if(options[i].value == genderVal){
- options[i].selected=true;
- break;
- }
- }
- }
- </script>
- <body οnlοad="initPage();">
- <div style="margin-left: 100px; margin-top: 100px;">
- <div>
- <font color="red">${errorMsg }</font>
- </div>
- <div>
- <form action="<%=context %>/sublist/SublistServlet" id="stuForm" method="post">
- 姓名
- <input type="text" name="stuName" id="stu_name" style="width:120px" value="${stuName }">
- 性别
- <select name="gender" id="gender" style="width:80px">
- <option value="0">全部</option>
- <option value="1">男</option>
- <option value="2">女</option>
- </select>
- <input type="submit" value="查询">
- </form>
- </div>
- <br>
- 学生信息列表:<br>
- <br>
- <!-- 后台返回结果为空 -->
- <c:if test="${fn:length(result.dataList) eq 0 }">
- <span>查询的结果不存在</span>
- </c:if>
- <!-- 后台返回结果不为空 -->
- <c:if test="${fn:length(result.dataList) gt 0 }">
- <table border="1px" cellspacing="0px"
- style="border-collapse: collapse">
- <thead>
- <tr height="30">
- <th width="130">姓名</th>
- <th width="130">性别</th>
- <th width="130">年龄</th>
- <th width="190">家庭地址</th>
- </tr>
- </thead>
- <c:forEach items="${result.dataList }" var="student">
- <tr>
- <td><c:out value="${student.stuName}"></c:out></td>
- <td>
- <c:if test="${ student.gender eq 1}">男</c:if>
- <c:if test="${ student.gender eq 2}">女</c:if>
- </td>
- <td><c:out value="${student.age }"></c:out></td>
- <td><c:out value="${student.address }"></c:out></td>
- </tr>
- </c:forEach>
- </table>
- <br> 共${result.totalRecord }条记录共${result.totalPage }页 当前第${result.currentPage }页
- <a href="#" οnclick="firstPage();">首页</a>
- <a href="#" οnclick="nextPage();">下一页</a>
- <a href="#" οnclick="previousPage();">上一页</a>
- <a href="#" οnblur="lastPage();">尾页</a>
- </c:if>
- </div>
- </body>
- </html>
import java.util.List;
import cn.strutsdemo.pojo.House;
public class PageBean {
private List<House> list; // 通过hql从数据库分页查询出来的list集合
private int allRows;//总行数
private int totalPage;//总页数共页一共有多少页
private int currentPage;//当前所在页当前页
/**
* 得到总页数
*
* @param pageSize
* 每页记录数
* @param allRows
* 总记录数
* @return 总页数
*/
public int getTotalPages(int pageSize, int allRows) {
int totalPage = (allRows % pageSize == 0) ? (allRows / pageSize) : (allRows / pageSize) + 1;
return totalPage;
}
/**
* 得到当前开始记录号
*
* @param pageSize
* 每页记录数
* @param currentPage
* 当前页
* @return
*/
public int getCurrentPageOffset(int pageSize, int currentPage) {
int offset = pageSize * (currentPage - 1);
return offset;
}
/**
* 得到当前页, 如果为0 则开始第一页,否则为当前页
*
* @param page
* @return
*/
public int getCurPage(int page) {
int currentPage = (page == 0) ? 1 : page;
return currentPage;
}
public List<House> getList() {
return list;
}
public void setList(List<House> list) {
this.list = list;
}
public int getAllRows() {
return allRows;
}
public void setAllRows(int allRows) {
this.allRows = allRows;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
}