分頁一直是一個比較麻煩的問題,特別是在我作的這個系統中更是有大量的分頁,爲了應對該問題,特意寫了一個模板以方便代碼重用,該模板包括後臺分頁的模板、前端顯示的模板兩部分。css
1、分頁分析前端
分頁須要三種類型的參數:sql
1.系統啓動以後就可以肯定的參數,好比每頁顯示多少條數據pageSize,分頁長度:elementLength瀏覽器
2.瀏覽器動態請求的參數這種狀況分爲兩種:帶有請求的頁碼(requestPage)和不帶有請求的頁碼。服務器
因爲後臺的分頁代碼是重用的,因此第一次請求的時候就須要帶上請求的頁碼,若是不帶上請求的頁碼默認是1,這須要後臺代碼進行判斷。jsp
3.服務器響應的數據,好比首頁碼(startIndex)、尾頁碼(endIndex)、總共的頁碼(totalPages)、當前的頁碼(currentPage=requestPage),固然還有響應的數據。大數據
2、前端頁面this
發起分頁請求的多是一個超連接觸發,也有多是一個查詢按鈕觸發,請求的方法都是同一個方法。spa
1.超連接觸發hibernate
2.查詢按鈕觸發
對於超連接觸發的,能夠直接訪問action,可是查詢按鈕觸發的卻須要作一些動做才行。
(1)表單設置隱藏域,設置默認請求頁碼或者大多部分提供給js進行更改請求頁碼並提交給Action。
<s:hidden name="requestPage" value="1"></s:hidden>
(2)不能直接提交,須要先經過js進行設置:
/* *多條件查詢和分頁頁面使用的js */ $().ready(function(){ $("#pageSplit a").each(function(){ $(this).unbind("click"); $(this).bind("click",function(){ var requestPage=$(this).attr("href").split("requestPage=")[1]; $("input[name='requestPage']").val(requestPage); $("form").submit(); return false; }); }); $("#query").unbind("click"); $("#query").bind("click",function(){ $("form").submit(); }); });
#pageSplit a是前端的jsp(struts2)分頁模板,後邊介紹。
3.前端顯示的jsp分頁模板(struts2)
<div id="pageSplit"> <s:a>首頁 <s:param name="requestPage" value="1"></s:param> </s:a> <s:a>上一頁 <s:param name="requestPage" value="#requestPage-1>0?#requestPage-1:1"></s:param> </s:a> <s:iterator var="page" begin="%{#startIndex}" end="%{#endIndex}"> <s:if test="#page==#requestPage"> <s:a cssStyle="background-color: #91C0E3;"> <s:param name="requestPage" value="#page"></s:param> <s:property value="#page"/> </s:a> </s:if> <s:else> <s:a> <s:param name="requestPage" value="#page"></s:param> <s:property value="#page"/> </s:a> </s:else> </s:iterator> <s:if test="%{#totalPages>#endIndex}"> ...... <s:a> <s:param name="requestPage" value="#endIndex+1"></s:param> 共有 <s:property value="%{#totalPages}"/>頁</s:a> </s:if> <s:else> <s:a> <s:param name="requestPage" value="%{#totalPages}"></s:param> 共有 <s:property value="%{#totalPages}"/>頁</s:a> </s:else> <s:a> 下一頁 <s:param name="requestPage" value="#requestPage+1>#totalPages?#totalPages:#requestPage+1"></s:param> </s:a> <s:a> 尾頁 <s:param name="requestPage" value="#totalPages"></s:param> </s:a> </div>
結合的css樣式模板
#pageSplit{ margin-top:7px; margin-bottom:7px; font-size: 14px; text-align: center; } #pageSplit a{ display: inline-block; background-color:#CEE5EA; border :1px solid ; padding-top: 3px; padding-bottom: 3px; padding-left: 7px; padding-right:7px; color: #004779; text-decoration: none; } #pageSplit a:HOVER { background-color: #ADD8E5; } #query{ font-size:12px; width: 50px; height: 24px; text-align: center; margin: 0px; }
2、後臺分頁邏輯實現
1.經過監聽器肯定初始化的兩個參數:pageSize和elementLength
首先將參數放到配置文件中:init.properties
#every pages show 12 datas pageSize=10 #show the choose length prePage,1,2,3,4,5,6,7,8 nextPage splitPageLength=5
監聽器獲取
InputStream is=MyServletContextListener.class.getClassLoader().getResourceAsStream("init.properties"); Properties initProperties=new Properties(); initProperties.load(is); PageSplitConfig.splitPageLength=Integer.parseInt(initProperties.getProperty("splitPageLength")); PageSplitConfig.pageSize=Integer.parseInt(initProperties.getProperty("pageSize"));
這樣就將兩個參數封裝到了PageSplitConfig類中:
public class PageSplitConfig { //首先是每頁顯示多少條數據 public static Integer pageSize; //分頁的長度 public static Integer splitPageLength; }
2.Action中進行分頁的邏輯控制:
以showAllCards方法爲例:
public String showAllCards(){ //預配置代碼 /*Collection<Card>list=cardService.getAllCards(); ActionContext.getContext().put("cardlist", list);*/ Collection<CredentialType> credentialTypes=credentialTypeService.getAllCredentialTypes(); List<String> allCredentialTypes=new ArrayList<String>(); for(CredentialType temp:credentialTypes){ allCredentialTypes.add(temp.getCredentialTypeName()); } ActionContext.getContext().put("credentialTypes", allCredentialTypes); //預配置代碼結束 //獲取請求參數開始 HttpServletRequest request=ServletActionContext.getRequest(); String cardId=request.getParameter("cardId"); if(cardId==null||"".equals(cardId)){ ActionContext.getContext().put("cardId", ""); }else{ ActionContext.getContext().put("cardId", cardId); } String userName=request.getParameter("userName"); if(userName==null||"".equals(userName)){ ActionContext.getContext().put("userName", ""); }else{ ActionContext.getContext().put("userName",userName); } String typeofcredential=request.getParameter("typeofcredential"); if(typeofcredential==null||"".equals(typeofcredential)||"''".equals(typeofcredential)){ ActionContext.getContext().put("typeofcredential", ""); }else{ ActionContext.getContext().put("typeofcredential", typeofcredential); } String sex=request.getParameter("sex"); if(sex==null||"".equals(sex)||"不限".equals(sex)){ ActionContext.getContext().put("sex", "不限"); }else{ ActionContext.getContext().put("sex", sex); } String integral=request.getParameter("integral"); if(integral==null||"".equals(integral)){ ActionContext.getContext().put("integral", ""); }else{ ActionContext.getContext().put("integral", integral); } //獲取請求參數結束 //計算分頁參數開始 String requestPage=request.getParameter("requestPage"); if(requestPage==null||"".equals(requestPage.trim())){ requestPage="1"; } System.out.println("requestPage:"+requestPage); Collection<Card>cards=cardService.getCardsByMN(Integer.parseInt(requestPage),cardId,userName, typeofcredential,sex,integral); int totalLines=this.cardService.getTotalLines(Integer.parseInt(requestPage),cardId,userName, typeofcredential,sex,integral); System.out.println("totalLines:"+totalLines); PageSplitData.requestPage=Integer.parseInt(requestPage); PageSplitData.calculate(totalLines); //計算分頁參數結束 System.out.println("startIndex:"+PageSplitData.startIndex); System.out.println("endIndex:"+PageSplitData.endIndex); System.out.println("totalPages:"+PageSplitData.totalPages); System.out.println("查詢到的會員數量:"+cards.size()); ActionContext.getContext().put("startIndex",PageSplitData.startIndex); ActionContext.getContext().put("endIndex", PageSplitData.endIndex); ActionContext.getContext().put("requestPage",PageSplitData.requestPage); ActionContext.getContext().put("totalPages",PageSplitData.totalPages); ActionContext.getContext().put("employees", cards); ActionContext.getContext().put("cardlist", cards); return listAction; }
首先須要調用Service方法獲取數據和數據總量
Collection<Card>cards=cardService.getCardsByMN(Integer.parseInt(requestPage),cardId,userName, typeofcredential,sex,integral); int totalLines=this.cardService.getTotalLines(Integer.parseInt(requestPage),cardId,userName, typeofcredential,sex,integral);
(1)獲取指定分頁數據的方法:
public Collection<Card> getCardsByMN(int requestPage, String cardId, String userName, String typeofcredential, String sex, String integral) { int m=(requestPage-1)*PageSplitConfig.pageSize; int n=PageSplitConfig.pageSize; String sql="from Card where 1=1 "; if(cardId!=null&&!"".equals(cardId.trim())){ sql=sql+" and cardId='"+cardId.trim()+"'"; } if(userName!=null&&!"".equals(userName.trim())){ sql=sql+" and userName='"+userName.trim()+"'"; } if(typeofcredential!=null&&!"".equals(typeofcredential.trim())&&!"''".equals(typeofcredential.trim())){ sql=sql+" and credentialType.credentialTypeName='"+typeofcredential.trim()+"'"; } if(sex!=null&&!"".equals(sex.trim())&&!"不限".equals(sex.trim())){ sql=sql+" and sex='"+sex+"'"; } if(integral!=null&&!"".equals(integral.trim())){ sql=sql+" and integral='"+integral.trim()+"'"; } return this.cardDao.getAllCards(sql,m,n); }
該方法會調用DAO方法:
public Collection<Card> getAllCards(String sql, int m, int n) { Query query=this.hibernateTemplate.getSessionFactory().openSession().createQuery(sql); query.setFirstResult(m); query.setMaxResults(n); return query.list(); }
(2)獲取全部數據總量的方法:
public int getTotalLines(int requestPage, String cardId, String userName, String typeofcredential, String sex, String integral) { String sql="from Card where 1=1 "; if(cardId!=null&&!"".equals(cardId.trim())){ sql=sql+" and cardId='"+cardId.trim()+"'"; } if(userName!=null&&!"".equals(userName.trim())){ sql=sql+" and userName='"+userName.trim()+"'"; } if(typeofcredential!=null&&!"''".equals(typeofcredential.trim())&&!"".equals(typeofcredential.trim())){ sql=sql+" and credentialType.credentialTypeName='"+typeofcredential.trim()+"'"; } if(sex!=null&&!"".equals(sex.trim())&&!"不限".equals(sex.trim())){ sql=sql+" and sex='"+sex.trim()+"'"; } if(integral!=null&&!"".equals(integral.trim())){ sql=sql+" and integral='"+integral.trim()+"'"; } return this.cardDao.getAllCards(sql).size(); }
調用DAO方法實現:
public Collection<Card> getAllCards(String sql) { return this.hibernateTemplate.getSessionFactory().openSession().createQuery(sql).list(); }
(3)最重要的分頁邏輯的實如今SplitPageData類中:
public class PageSplitData { //該條數據應該在調用響應方法以前賦值 public static Integer requestPage; //請求以後應該強調顯示的頁碼,即響應以後的當前頁或者響應時的響應頁碼。 public static Integer startIndex; //起始頁碼 public static Integer endIndex; //最後頁碼 public static Integer totalPages; //一共有多少頁 /** * * @param total */ public static void calculate(int totalLines){ //每頁顯示多少條數據 int pageSize=PageSplitConfig.pageSize; //分頁長度 int splitPageLength=PageSplitConfig.splitPageLength; //已經獲得了數據一共有多少條:totalLines 和 請求頁 requestPage //獲得總頁數 totalPages=totalLines/pageSize+(totalLines%pageSize==0?0:1); //計算startIndex和endIndex的關鍵原則就是endIndex-startIndex的結果是splitPageLength-1 if(splitPageLength%2==0){//分頁長度是偶數,爲了讓當前頁在中間,採用前多後少的分頁方法 //這種狀況下splitPageLength/2+splitPageLength/2==splitPageLength startIndex=requestPage-(splitPageLength/2+1);//正常狀況(針對大數據) endIndex=requestPage+(splitPageLength/2);//特殊狀況(針對大數據) }else{//分頁長度是奇數 //這種狀況下splitPageLength/2+splitPageLength/2=splitPageLength-1,符合以前說的原則 startIndex=requestPage-(splitPageLength/2);//這樣就正好了 endIndex=requestPage+(splitPageLength/2);//正好 } if(startIndex<=0){ startIndex=1; if((startIndex+splitPageLength-1)>totalPages){ endIndex=totalPages; }else{ endIndex=startIndex+splitPageLength-1; } }else{//正常狀況 if(endIndex>totalPages){ endIndex=totalPages; if((endIndex-(splitPageLength-1))<=0){ startIndex=1; }else{ startIndex=endIndex-(splitPageLength-1); } }else{ //正常狀況,不作處理 } } //須要傳遞的幾個參數都計算完畢 } public static Integer getRequestPage() { return requestPage; } public static Integer getStartIndex() { return startIndex; } public static Integer getEndIndex() { return endIndex; } public static Integer getTotalPages() { return totalPages; } }
3、總結
該分頁模板須要的參數經過三種途徑傳到PageSplitData類中
1.監聽器傳遞pageSize和elementLength兩個參數
2.經過set方法設置請求頁requestPage
3.直接傳遞totalLines
計算結果包括
1.首頁碼:startIndex
2.尾頁碼:endIndex
3.總頁數:totalPages
#pageSplit a