這是我學(xué)習Struts半個(gè)月以來(lái),在開(kāi)發(fā)第一個(gè)留言簿的時(shí)候,參考了網(wǎng)上很多的方案,然后做的一套Web分頁(yè)機制,使用Struts的MVC方式,利用Hibernate的分段查詢(xún)的機制來(lái)實(shí)現,JSP頁(yè)面干凈不含Java代碼,邏輯結構清晰,易于擴展。是一個(gè)比較好的完整的分頁(yè)解決方案。
目前為第一個(gè)版本,以后會(huì )逐步完善,在這里希望能起到一個(gè)拋磚引玉的作用
大家有什么好的建議可以與我聯(lián)系:
jeffreyxu@gmail.com
閱讀門(mén)檻:
Java基礎知識
Struts基礎知識
對Hibernate有一定了解
<!--[if !supportLists]-->一、 <!--[endif]-->開(kāi)發(fā)環(huán)境
SQLServer2000
<!--[if !supportLists]-->二、 <!--[endif]-->開(kāi)發(fā)思路
分頁(yè)的步驟:
按照Struts 的MVC處理方式,對于顯示數據的請求要先提交至相應的Action(這里是DisplayAction)進(jìn)行處理,查詢(xún)數據庫,根據數據總數初始化分頁(yè)信息,然后從數據庫取得第一頁(yè)所要顯示的數據(這里并沒(méi)有全部一次查詢(xún)所有數據,效率較高),然后轉交至相應的顯示頁(yè)面顯示。
<!--[if !supportLists]-->三、 <!--[endif]-->源碼部分
<!--[if !supportLists]-->1) <!--[endif]-->Hibernate 部分:
HibernateUtil Hibernate實(shí)用類(lèi),負責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 查詢(xún)參數
ParasList 查詢(xún)參數集合
HQuery 封裝了查詢(xún)參數的查詢(xún)信息類(lèi)
HibernateDAO 根據傳遞進(jìn)來(lái)的HQuery進(jìn)行數據庫的查詢(xún)
有關(guān)以上三個(gè)類(lèi)的具體細節,請參考我收藏的文章:Hibernate查詢(xún)解決方案
<!--[if !supportLists]-->2) <!--[endif]-->Pager 包含了分頁(yè)信息的類(lèi),包括頁(yè)面總數,記錄總數,當前第幾頁(yè)
/*
* @(#)Pager.java
*
* Copyright (c) 2005, Jeffrey Hsu
*/
package com.jeffrey.messagelove;
/**
* Pager holds the page info.
*/
public class Pager {
private int totalRows = 0; // 記錄總數
private int totalPages = 0; // 總頁(yè)數
private int pageSize = 10; // 每頁(yè)顯示數據條數,默認為10條記錄
private int currentPage = 1; // 當前頁(yè)數
private boolean hasPrevious = false; // 是否有上一頁(yè)
private boolean hasNext = false; // 是否有下一頁(yè)
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(); // 刷新當前頁(yè)面信息
}
/**
* @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();
}
// 跳到第一頁(yè)
public void first() {
currentPage = 1;
this.setHasPrevious(false);
refresh();
}
// 取得上一頁(yè)(重新設定當前頁(yè)面即可)
public void previous() {
currentPage--;
refresh();
}
// 取得下一頁(yè)
public void next() {
System.out.println("next: totalPages: " + totalPages +
" currentPage : " + currentPage);
if (currentPage < totalPages) {
currentPage++;
}
refresh();
}
// 跳到最后一頁(yè)
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;
}
// 刷新當前頁(yè)面信息
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 顯示數據頁(yè)面控制器
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.*;
/**
* 顯示頁(yè)面控制器
*/
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");
// 初始化頁(yè)面信息
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");
// 跳轉至相應頁(yè)面
if (viewPage != null && !viewPage.equals("")) {
try {
pager.setCurrentPage(Integer.parseInt(viewPage));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
if (action != null) {
// 根據傳遞進(jìn)來(lái)的參數控制頁(yè)面的前進(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頁(yè)面 分頁(yè)導航代碼:
<%-- 分頁(yè)導航 --%>
<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"/>頁(yè)
</td>
<td align="right" width="60">
<html:link page="/Displayall.do?viewPage=&action=first">首頁(yè)</html:link>
</td>
<td align="right" width="60">
<logic:equal name="pager" property="hasPrevious" value="true">
<html:link page="/Displayall.do?viewPage=&action=previous">上一頁(yè)</html:link>
</logic:equal>
<logic:equal name="pager" property="hasPrevious" value="false">
<span class="invalidLink">上一頁(yè)</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">下一頁(yè)</html:link>
</logic:equal>
<logic:equal name="pager" property="hasNext" value="false">
<span class="invalidLink">下一頁(yè)</span>
</logic:equal>
</td>
<td width="60">
<html:link page="/Displayall.do?viewPage=&action=last">末頁(yè)</html:link>
</td>
<td width="160" align="rigth">
<%-- 跳轉相應頁(yè)面,參見(jiàn)下文頁(yè)面跳轉部分 --%>
<html:form action="/ViewPage.do">
跳轉到
<html:text property="targetPage" size="3" maxlength="3"/>
<html:submit value="GO"/>
</html:form>
</td>
<td>
</td>
</tr>
</table>
<%-- 分頁(yè)導航結束 --%>
<!--[if !supportLists]-->5) <!--[endif]-->頁(yè)面跳轉部分:
Form:
ViewPageForm
/*
* @(#)ViewPageForm.java
*
* Copyright (c) 2005, Jeffrey Xu
*/
package com.jeffrey.messagelove;
import org.apache.struts.action.*;
public class ViewPageForm extends ActionForm {
// 欲跳轉的目標頁(yè)面
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:
根據Form傳遞進(jìn)來(lái)的目標頁(yè)面信息跳轉之相應的頁(yè)面
如果輸入的數字合法,則跳轉至相應的頁(yè)面,否則跳轉至當前頁(yè)面(在用戶(hù)看來(lái)頁(yè)面沒(méi)有變化)
/*
* @(#)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 {
// 判斷是否超出頁(yè)面范圍
if ((Integer.parseInt(targetPage) > pager.getTotalPages()) ||
(Integer.parseInt(targetPage) < 1)) {
targetPage = String.valueOf(pager.getCurrentPage());
}
// 如果輸入的不是數字,也就是拋出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]-->結束:
代碼已經(jīng)全部結束,但是總覺(jué)得JSP頁(yè)面的代碼太多,期待有更好的解決辦法,比如封裝成自定義JSP標簽Tag,復用度更高。
還有就是頁(yè)面跳轉部分我想做成下拉列表的方式,根據總頁(yè)數來(lái)動(dòng)態(tài)生成下拉列表,這樣更方便一些,并且可以避免用戶(hù)的錯誤輸入,但我不知該如何根據總頁(yè)數來(lái)動(dòng)態(tài)生成下拉列表,希望哪位朋友能夠給出一個(gè)解決辦法。
聯(lián)系客服