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{
-
-
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();
-
}
-
-
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">
-
<% "c" uri= "http://java.sun.com/jsp/jstl/core" %>prefix=
-
<% "fn" uri= "http://java.sun.com/jsp/jstl/functions" %>prefix=
-
<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 onload= "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= "#" onclick= "firstPage();">首页</a>
-
<a href= "#" onclick= "nextPage();">下一页</a>
-
<a href= "#" onclick= "previousPage();">上一页</a>
-
<a href= "#" onblur= "lastPage();">尾页</a>
-
</c: if>
-
</div>
-
</body>
-
</html>