最近在學習JavaWeb的時候,用到了分頁功能,現在進行一個記錄,以備不時之需
第一步:先完成PageBean的編寫
就是對目前頁數,每頁顯示的記錄數,總記錄數,總頁數,分頁顯示的資訊進行封裝。作為通用的分頁功能的實作,這裡用到了泛型
importjava.util.List;
public class PageBean{private int currPage;//目前頁數
private int pageSize;//每頁顯示記錄數
private int totalCount;//總記錄數
private int totalPage;//總頁數
private List list;//每頁顯示的資訊
public intgetCurrPage() {returncurrPage;
}public void setCurrPage(intcurrPage) {this.currPage =currPage;
}public intgetPageSize() {returnpageSize;
}public void setPageSize(intpageSize) {this.pageSize =pageSize;
}public intgetTotalCount() {returntotalCount;
}public void setTotalCount(inttotalCount) {this.totalCount =totalCount;
}public intgetTotalPage() {returntotalPage;
}public void setTotalPage(inttotalPage) {this.totalPage =totalPage;
}public ListgetList() {returnlist;
}public void setList(Listlist) {this.list =list;
}
}
第二步:在Action類中編寫一個分頁方法
Action中通過調用業務層Service類的分頁方法,Employee就是具體的資訊Bean,之前泛型的使用就在于此,在不同項目中使用不同的資訊Bean可以完成多種類資訊的分頁,employeeService就是具體的業務層Service,Service中我們也有一個叫findAll的方法。這裡的currPage生成其set/get方法,等使用者點選了頁面及具體的頁數,Struts2會獲得具體的頁數,然後将currPage傳給Service
//分頁(目前頁)這裡等于1是為了使第一頁為預設頁
private int currPage = 1;public intgetCurrPage() {returncurrPage;
}public void setCurrPage(intcurrPage) {this.currPage =currPage;
}
publicString findAll() {
PageBean pageBean =employeeService.findAll(currPage);
ActionContext.getContext().getValueStack().push(pageBean);return "findAll";
}
第三步:編寫Service中的分頁方法
先生成一個PageBean對象(注意泛型),之後開始封裝這個Bean。pageSize(每頁顯示的記錄數)這裡設定為3,就是每頁顯示3條記錄,totalCount(總記錄數)通過Dao中的findCount()方法來查到,totalPage(總頁數)=totalCount(總記錄數)/pageSize(每頁大小),Math.ceil可以獲得一個double的近似值(大于等于),之後我們通過Double包裝類的intValue再轉成int型,begin(每一頁的開頭的序号),list的資料也通過Dao的findPage(int,int)方法獲得
public PageBean findAll(intcurrPage) {
PageBean pageBean = new PageBean<>();//封裝pageBean
pageBean.setCurrPage(currPage);int pageSize = 3;
pageBean.setPageSize(pageSize);int totalCount =employeeDao.findCount();
pageBean.setTotalCount(totalCount);
Double totalPage= Math.ceil((double) totalCount /pageSize);
pageBean.setTotalPage(totalPage.intValue());int begin = (currPage - 1) *pageSize;
List list =employeeDao.findPage(begin, pageSize);
pageBean.setList(list);returnpageBean;
}
第四步:編寫Dao中的方法
這之前在Service中使用的findCount()和findPage(int,int),值得注意的就是findCount()中的hql語句使用count(*),還有就是findPage(int,int)中使用了org.hibernate.criterion.DetachedCriteria類,查詢時不是用find方法,而是findByCriteria來查詢
public intfindCount() {
String hql="select count(*) from Employee";
List list = (List) hibernateTemplate.find(hql);if(list.size()>0){return list.get(0).intValue();
}return 0;
}
public List findPage(int begin, intpageSize) {
DetachedCriteria criteria=DetachedCriteria.forClass(Employee.class);
List list = (List) hibernateTemplate.findByCriteria(criteria, begin, pageSize);returnlist;
}
基本上通過以上四步就完成了分頁功能邏輯代碼的編寫,接下來就是對視圖層頁面的編寫
下面是個分頁的簡單顯示,處于首頁時,隻顯示下一頁和尾頁,處于尾頁時,隻顯示首頁和上一頁,其他頁就都顯示。這裡使用的Struts2的标簽庫,是以不要忘了要加上
為什麼我們可以直接currPage,totalPage等屬性?是因為我們之前将PageBean對象放入了值棧中
第/頁
總記錄數:/每頁顯示:條
[首頁]
">[上一頁]
">[下一頁]
">[尾頁]
效果圖:

可以使用了struts2的标簽來進行疊代顯示資料,這裡給個參考
編輯
删除
注意:一定要在Struts.xml檔案中配置轉跳到我們編寫的action上(在這裡是department_findAll.action),不然打開要分頁的頁面時,不會進行分頁操作,隻有你選擇了頁數才會分頁
後記
我在使用的過程中發現,要使用分頁功能的地方不少,在某些地方,使用上面的會出錯:例如對條件查詢之後的結果進行分頁,第一頁很OK,但是你點選下一頁/某一頁的時候會出現查詢條件的丢失問題,再進行的查詢結果分頁是沒有條件的,就會出錯
解決辦法(我使用Servlet+JDBC實作的,原理是一樣的):
在我們的POJO中添加一個url屬性,表示查詢條件,因為POST方式條件是放在請求頭中的,很不友善,是以再進行條件查詢的的表單使用GET方式:
"method="get">
我們需要獲得這個url(包括項目名+Servlet名+條件),獲得這個url封裝到POJO中
改進後的PageBean:
importjava.util.List;public class PageBean{//目前頁
private intcurrPage;//每頁記錄數
private intpageSize;//總記錄數
private inttotalCount;//資料集合
private Listlist;//url表示條件查詢的條件(GET方式)
privateString url;public intgetCurrPage() {returncurrPage;
}public void setCurrPage(intcurrPage) {this.currPage =currPage;
}public intgetPageSize() {returnpageSize;
}public void setPageSize(intpageSize) {this.pageSize =pageSize;
}public intgetTotalCount() {returntotalCount;
}public void setTotalCount(inttotalCount) {this.totalCount =totalCount;
}//設定總頁數(計算得出)
public intgetTotalPage() {
Double totalPage=Math.ceil((double)totalCount/pageSize);returntotalPage.intValue();
}public ListgetList() {returnlist;
}public void setList(Listlist) {this.list =list;
}publicString getUrl() {returnurl;
}public voidsetUrl(String url) {this.url =url;
}
}
控制層要添加的方法(encoding()方法根據情況添加):
privateString getURL(HttpServletRequest request){
String contextPath=request.getContextPath(); //項目名
String servletPath=request.getServletPath(); //servlet路徑,即
private Customer encoding(Customer customer) throwsUnsupportedEncodingException{
String cname=customer.getCname();
String gender=customer.getGender();
String cellPhone=customer.getCellphone();
String email=customer.getEmail();if(cname!=null&&!cname.isEmpty()){//cname=new String(cname.getBytes("ISO-8859-1"),"UTF-8");//tomcat8之前tomcat預設字元編碼使用是ISO-8859-1
cname=new String(cname.getBytes(),"UTF-8");
customer.setCname(cname);
}if(gender!=null&&!gender.isEmpty()){//gender=new String(gender.getBytes("ISO-8859-1"),"UTF-8");
gender=new String(gender.getBytes("ISO-8859-1"),"UTF-8");
customer.setCname(gender);
}if(cellPhone!=null&&!cellPhone.isEmpty()){//cellPhone=new String(cellPhone.getBytes("ISO-8859-1"),"UTF-8");
cellPhone=new String(cellPhone.getBytes(),"UTF-8");
customer.setCname(cellPhone);
}if(email!=null&&!email.isEmpty()){//email=new String(email.getBytes("ISO-8859-1"),"UTF-8");
email=new String(email.getBytes(),"UTF-8");
customer.setCname(email);
}returncustomer;
}
這個geturl()方法就是獲得url的方法,我用來表示目前頁的變量使用的是currPage,根據實際情況更換。encoding()方法是處理get方式獲得的條件中文亂碼問題,如果項目使用tomcat8之後的伺服器就不用轉碼了。注意:現在是所有的查詢的方法的需要使用geturl()方法,并将傳回值封裝到POJO中。使用request.getRequestURI()方法也可以獲得Struts2中Action的位址。使用架構開發應該就不用考慮encoding()這個編碼方法,隻需要處理geturl()方法了
多條件查詢的Servlet方法:
public String query(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {//獲得查詢條件
Customer customer=CommonUtils.toBean(request.getParameterMap(), Customer.class);//處理GET請求的編碼格式//customer = encoding(customer); 因為我的tomcat是8.5,是以就不轉碼了//處理PageBean
int pageSize=10; //每頁記錄數為10
int currPage=getCurrentPage(request);int begin=(currPage-1)*pageSize; //計算每頁的開頭
PageBean pageBean=customerService.query(customer,begin,pageSize);//封裝目前頁和每頁記錄數
pageBean.setCurrPage(currPage);
pageBean.setPageSize(pageSize);//封裝url
pageBean.setUrl(getURL(request));//将pageBean儲存request
request.setAttribute("pb", pageBean);return "f:/list.jsp";
}
注意:因為這種方式的頁碼算是使用的超連接配接,是以currPage可能會被惡意輸入,需要驗證一下,這裡粘一個使用正則驗證是否是數字的方法(其實不僅僅要驗證是否為數字,還應該驗證目前頁不要大于總頁數,也不要小于1):
public static booleanisNum(String string) {
Pattern pattern=Pattern.compile("[1-9]{1}\\d*");
Matcher matcher=pattern.matcher(string);returnmatcher.matches();
}
Dao中多條件查詢:
public PageBean query(Customer customer, int begin, intpageSize) {try{
PageBean pageBean=new PageBean();StringBuilder cntSql=new StringBuilder("select count(*) from t_customer");
StringBuilder whereSql=new StringBuilder(" where 1=1");
List params=new ArrayList();
String cname=customer.getCname();if(cname!=null&&!cname.trim().isEmpty()){
whereSql.append(" and cname like ?");
params.add("%"+cname+"%");
}
String gender=customer.getGender();if(gender!=null&&!gender.trim().isEmpty()){whereSql.append(" and gender=?");
params.add(gender);
}
String phone=customer.getCellphone();if(phone!=null&&!phone.trim().isEmpty()){
whereSql.append(" and cellphone like ?");
params.add("%"+phone+"%");
}
String email=customer.getEmail();if(email!=null&&!email.trim().isEmpty()){
whereSql.append(" and email like ?");
params.add("%"+email+"%");
}//運作sql
Number count=(Number) qr.query(cntSql.append(whereSql).toString(), newScalarHandler(),params.toArray());
pageBean.setTotalCount(count.intValue());StringBuilder listSql=new StringBuilder("select * from t_customer");//limit子句分頁
StringBuilder limitSql=new StringBuilder(" order by cname limit ?,?");//添加這兩個參數
params.add(begin);
params.add(pageSize);//運作sql
List beanList=qr.query(listSql.append(whereSql).append(limitSql).toString(),new BeanListHandler(Customer.class),
params.toArray());
pageBean.setList(beanList);returnpageBean;
}catch(Exception e) {
e.printStackTrace();
}return null;
}
我還是使用的是拼接sql的方式,與衆不同的是分頁中使用的count語句limit語句都是帶where條件的
在頁面中也需要進行相應的修改(我這裡使用的是JSTL):
第${pb.currPage }頁/共${pb.totalPage }頁1 }">
首頁
上一頁
下一頁
尾頁
pb就是我放在request中的pageBean的名字,注意url需要我們從pageBean的url中取出,頁面隻關心目前頁,不去關心路徑到底是什麼
一個頁碼的實作
可能說一個頁碼又什麼好實作的,直接把所有頁數寫出來,都加上超連結不就好了,但是觀察百度等有頁碼的網站,你會發現頁面是會随着頁數變換的,比如說:先顯示10頁,但是當你點選第7頁的時候,第1頁應該隐藏,第11頁應該出現,隻有出現11頁我們才能點選,這就是要實作的功能
10,計算begin和end--%>
pb.totalPage }">
[${i }]
[${i }]
這是一個顯示10頁,點選第7頁後,1頁消失11頁出現,點選8頁後,2頁消失12頁出現,以此類推
效果圖(這是我把頁碼放在上一頁和下一頁之間的效果):