天天看點

【Web】分頁簡單實作

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實作分頁。

【Web】分頁簡單實作

建立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");
	}
}
           

分頁對象 Pager類

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);
	}
}
           

資料庫工具類 JdbcUtil.java

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);
}
           

Dao層接口實作類 SublistStudentDaoImpl.java

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;
	}
}
           

建立Service層,調用Dao層

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;
	}
}
           

建立Servlet,接收參數,調用Service層

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);
	}
}
           

Jsp頁面

<%@ 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  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="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  οnclick="firstPage();">首頁</a>   
			<a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  οnclick="nextPage();">下一頁</a>   
			<a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  οnclick="previousPage();">上一頁</a>  
			<a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  οnblur="lastPage();">尾頁</a>	
		</c:if>
	</div>
</body>
</html>