這是我學(xué)習(xí)Struts半個月以來,在開發(fā)第一個留言簿的時候,參考了網(wǎng)上很多的方案,然后做的一套Web分頁機(jī)制,使用Struts的MVC方式,利用Hibernate的分段查詢的機(jī)制來實(shí)現(xiàn),JSP頁面干凈不含Java代碼,邏輯結(jié)構(gòu)清晰,易于擴(kuò)展。是一個比較好的完整的分頁解決方案。
目前為第一個版本,以后會逐步完善,在這里希望能起到一個拋磚引玉的作用
大家有什么好的建議可以與我聯(lián)系:
jeffreyxu@gmail.com
閱讀門檻:
Java基礎(chǔ)知識
Struts基礎(chǔ)知識
對Hibernate有一定了解
<!--[if !supportLists]-->一、 <!--[endif]-->開發(fā)環(huán)境
SQLServer2000
<!--[if !supportLists]-->二、 <!--[endif]-->開發(fā)思路
分頁的步驟:
按照Struts 的MVC處理方式,對于顯示數(shù)據(jù)的請求要先提交至相應(yīng)的Action(這里是DisplayAction)進(jìn)行處理,查詢數(shù)據(jù)庫,根據(jù)數(shù)據(jù)總數(shù)初始化分頁信息,然后從數(shù)據(jù)庫取得第一頁所要顯示的數(shù)據(jù)(這里并沒有全部一次查詢所有數(shù)據(jù),效率較高),然后轉(zhuǎn)交至相應(yīng)的顯示頁面顯示。
<!--[if !supportLists]-->三、 <!--[endif]-->源碼部分
<!--[if !supportLists]-->1) <!--[endif]-->Hibernate 部分:
HibernateUtil Hibernate實(shí)用類,負(fù)責(zé)Session的取得和關(guān)閉
/*
* @(#)HibernateUtil.java
*
* Copyright (c) 2005, Jeffrey Hsu
*/
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure()
.buildSessionFactory();
} catch (HibernateException ex) {
throw new RuntimeException("Exception building SessionFactory: " +
ex.getMessage(), ex);
}
}
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
//Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null) {
s.close();
}
}
}
Paras 查詢參數(shù)
ParasList 查詢參數(shù)集合
HQuery 封裝了查詢參數(shù)的查詢信息類
HibernateDAO 根據(jù)傳遞進(jìn)來的HQuery進(jìn)行數(shù)據(jù)庫的查詢
有關(guān)以上三個類的具體細(xì)節(jié),請參考我收藏的文章:Hibernate查詢解決方案
<!--[if !supportLists]-->2) <!--[endif]-->Pager 包含了分頁信息的類,包括頁面總數(shù),記錄總數(shù),當(dāng)前第幾頁
/*
* @(#)Pager.java
*
* Copyright (c) 2005, Jeffrey Hsu
*/
package com.jeffrey.messagelove;
/**
* Pager holds the page info.
*/
public class Pager {
private int totalRows = 0; // 記錄總數(shù)
private int totalPages = 0; // 總頁數(shù)
private int pageSize = 10; // 每頁顯示數(shù)據(jù)條數(shù),默認(rèn)為10條記錄
private int currentPage = 1; // 當(dāng)前頁數(shù)
private boolean hasPrevious = false; // 是否有上一頁
private boolean hasNext = false; // 是否有下一頁
public Pager() {
}
/**
* Initialize Pager
* @param totalRows total record rows
* @param pageSize total record is hold by every page
*/
public void init(int totalRows, int pageSize) {
this.totalRows = totalRows;
this.pageSize = pageSize;
totalPages = ((totalRows + pageSize) - 1) / pageSize;
refresh(); // 刷新當(dāng)前頁面信息
}
/**
* @return Returns the currentPage.
*/
public int getCurrentPage() {
return currentPage;
}
/**
* @param currentPage current page
*/
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
refresh();
}
/**
* @return Returns the pageSize.
*/
public int getPageSize() {
return pageSize;
}
/**
* @param pageSize The pageSize to set.
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
refresh();
}
/**
* @return Returns the totalPages.
*/
public int getTotalPages() {
return totalPages;
}
/**
* @param totalPages The totalPages to set.
*/
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
refresh();
}
/**
* @return Returns the totalRows.
*/
public int getTotalRows() {
return totalRows;
}
/**
* @param totalRows The totalRows to set.
*/
public void setTotalRows(int totalRows) {
this.totalRows = totalRows;
refresh();
}
// 跳到第一頁
public void first() {
currentPage = 1;
this.setHasPrevious(false);
refresh();
}
// 取得上一頁(重新設(shè)定當(dāng)前頁面即可)
public void previous() {
currentPage--;
refresh();
}
// 取得下一頁
public void next() {
System.out.println("next: totalPages: " + totalPages +
" currentPage : " + currentPage);
if (currentPage < totalPages) {
currentPage++;
}
refresh();
}
// 跳到最后一頁
public void last() {
currentPage = totalPages;
this.setHasNext(false);
refresh();
}
public boolean isHasNext() {
return hasNext;
}
/**
* @param hasNext The hasNext to set.
*/
public void setHasNext(boolean hasNext) {
this.hasNext = hasNext;
}
public boolean isHasPrevious() {
return hasPrevious;
}
/**
* @param hasPrevious The hasPrevious to set.
*/
public void setHasPrevious(boolean hasPrevious) {
this.hasPrevious = hasPrevious;
}
// 刷新當(dāng)前頁面信息
public void refresh() {
if (totalPages <= 1) {
hasPrevious = false;
hasNext = false;
} else if (currentPage == 1) {
hasPrevious = false;
hasNext = true;
} else if (currentPage == totalPages) {
hasPrevious = true;
hasNext = false;
} else {
hasPrevious = true;
hasNext = true;
}
}
}
<!--[if !supportLists]-->3) <!--[endif]-->Action:
DisplayAllAction 顯示數(shù)據(jù)頁面控制器
package com.jeffrey.messagelove;
import com.jeffrey.messagelove.*;
import com.jeffrey.messagelove.Pager;
import com.jeffrey.messagelove.hibernate.*;
/*
* @(#)DisplayAction.java
*
* Copyright (c) 2005, Jeffrey Xu
*/
import org.apache.struts.action.*;
import java.util.*;
import javax.servlet.http.*;
/**
* 顯示頁面控制器
*/
public class DisplayAllAction extends Action {
private HibernateDAO hibernateDAO = new HibernateDAO();
private Pager pager = new Pager();
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
HttpSession session = request.getSession();
List messageList = null;
HQuery hquery = new HQuery();
int totalRows = 0;
int startRow = 0;
try {
totalRows = hibernateDAO.getRows("select count(*) from Message");
// 初始化頁面信息
pager.init(totalRows, Constants.RECORD_PER_PAGE);
} catch (Exception ex) {
ex.printStackTrace();
}
hquery.setQueryString("From Message order by m_sendDate desc");
String viewPage = (String) request.getParameter("viewPage");
String action = (String) request.getParameter("action");
// 跳轉(zhuǎn)至相應(yīng)頁面
if (viewPage != null && !viewPage.equals("")) {
try {
pager.setCurrentPage(Integer.parseInt(viewPage));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
if (action != null) {
// 根據(jù)傳遞進(jìn)來的參數(shù)控制頁面的前進(jìn)后退
if (action.equalsIgnoreCase("previous")) {
pager.previous();
} else if (action.equalsIgnoreCase("next")) {
pager.next();
} else if (action.equalsIgnoreCase("first")) {
pager.first();
} else if (action.equalsIgnoreCase("last")) {
pager.last();
}
}
try {
hquery.setPageStartNo(pager.getCurrentPage());
messageList = hibernateDAO.find(hquery);
} catch (Exception ex) {
ex.printStackTrace();
}
request.setAttribute("list", messageList);
session.setAttribute("pager", pager);
return mapping.findForward("display");
}
}
<!--[if !supportLists]-->4) <!--[endif]-->JSP頁面 分頁導(dǎo)航代碼:
<%-- 分頁導(dǎo)航 --%>
<table border="0" width="780" class="pageInfo">
<tr>
<td width="250">
共 <bean:write name="pager" property="totalRows"/><span class="pageInfo">條記錄 </span>
第 <bean:write name="pager" property="currentPage"/>/<bean:write name="pager" property="totalPages"/>頁
</td>
<td align="right" width="60">
<html:link page="/Displayall.do?viewPage=&action=first">首頁</html:link>
</td>
<td align="right" width="60">
<logic:equal name="pager" property="hasPrevious" value="true">
<html:link page="/Displayall.do?viewPage=&action=previous">上一頁</html:link>
</logic:equal>
<logic:equal name="pager" property="hasPrevious" value="false">
<span class="invalidLink">上一頁</span>
</logic:equal>
</td>
<td align="center" width="4">
|
</td>
<td align="left" width="60">
<logic:equal name="pager" property="hasNext" value="true" >
<html:link page="/Displayall.do?viewPage=&action=next">下一頁</html:link>
</logic:equal>
<logic:equal name="pager" property="hasNext" value="false">
<span class="invalidLink">下一頁</span>
</logic:equal>
</td>
<td width="60">
<html:link page="/Displayall.do?viewPage=&action=last">末頁</html:link>
</td>
<td width="160" align="rigth">
<%-- 跳轉(zhuǎn)相應(yīng)頁面,參見下文頁面跳轉(zhuǎn)部分 --%>
<html:form action="/ViewPage.do">
跳轉(zhuǎn)到
<html:text property="targetPage" size="3" maxlength="3"/>
<html:submit value="GO"/>
</html:form>
</td>
<td>
</td>
</tr>
</table>
<%-- 分頁導(dǎo)航結(jié)束 --%>
<!--[if !supportLists]-->5) <!--[endif]-->頁面跳轉(zhuǎn)部分:
Form:
ViewPageForm
/*
* @(#)ViewPageForm.java
*
* Copyright (c) 2005, Jeffrey Xu
*/
package com.jeffrey.messagelove;
import org.apache.struts.action.*;
public class ViewPageForm extends ActionForm {
// 欲跳轉(zhuǎn)的目標(biāo)頁面
private String targetPage;
/**
* @return Returns the tagetPage.
*/
public String getTargetPage() {
return targetPage;
}
/**
* @param tagetPage The tagetPage to set.
*/
public void setTargetPage(String targetPage) {
this.targetPage = targetPage;
}
}
Action:
根據(jù)Form傳遞進(jìn)來的目標(biāo)頁面信息跳轉(zhuǎn)之相應(yīng)的頁面
如果輸入的數(shù)字合法,則跳轉(zhuǎn)至相應(yīng)的頁面,否則跳轉(zhuǎn)至當(dāng)前頁面(在用戶看來頁面沒有變化)
/*
* @(#)ViewPageAction.java
*
* Copyright (c) 2005, Jeffrey Xu
*/
package com.jeffrey.messagelove;
import org.apache.struts.action.*;
import javax.servlet.http.*;
public class ViewPageAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String targetPage = ((ViewPageForm) form).getTargetPage();
HttpSession session = request.getSession();
Pager pager = (Pager) session.getAttribute("pager");
try {
// 判斷是否超出頁面范圍
if ((Integer.parseInt(targetPage) > pager.getTotalPages()) ||
(Integer.parseInt(targetPage) < 1)) {
targetPage = String.valueOf(pager.getCurrentPage());
}
// 如果輸入的不是數(shù)字,也就是拋出NumberFormatException異常,
} catch (NumberFormatException e) {
e.printStackTrace();
targetPage = String.valueOf(pager.getCurrentPage());
}
request.removeAttribute(mapping.getAttribute());
return (new ActionForward("/Displayall.do?viewPage=" + targetPage));
}
}
<!--[if !supportLists]-->四、 <!--[endif]-->相關(guān)配置
<form-beans>
<form-bean name="ViewPageForm" type="com.jeffrey.messagelove.ViewPageForm"/>
</form-beans>
<global-forwards>
<!-- Default forward to "Welcome" action -->
<!-- Demonstrates using index.jsp to forward -->
<forward
name="displayall"
path="/Displayall.do?viewPage=1"/>
</global-forwards>
<!-- =========================================== Action Mapping Definitions -->
<action-mappings>
<!-- Default "Welcome" action -->
<!-- Forwards to Welcome.jsp -->
<action
path="/Displayall"
type="com.jeffrey.messagelove.DisplayAllAction"
scope="request"
validate="false"
>
</action>
<action
path="/ViewPage"
type="com.jeffrey.messagelove.ViewPageAction"
name="ViewPageForm"
scope="request"
validate="false"
>
<forward name="viewPage" path="/displayall.do?viewPage="/>
</action>
</action-mappings>
<!--[if !supportLists]-->五、 <!--[endif]-->結(jié)束:
代碼已經(jīng)全部結(jié)束,但是總覺得JSP頁面的代碼太多,期待有更好的解決辦法,比如封裝成自定義JSP標(biāo)簽Tag,復(fù)用度更高。
還有就是頁面跳轉(zhuǎn)部分我想做成下拉列表的方式,根據(jù)總頁數(shù)來動態(tài)生成下拉列表,這樣更方便一些,并且可以避免用戶的錯誤輸入,但我不知該如何根據(jù)總頁數(shù)來動態(tài)生成下拉列表,希望哪位朋友能夠給出一個解決辦法。