Appfuse與分頁

Appfuse使用的分頁Plugin是一個叫做DisplayTag的第三方插件,不過Appfuse並沒有完全實作這個部份;所以,當我們的資料多到需要分頁時,Appfuse的預設程式是:

  1. 將所有資料撈出來。

  2. 將所有資料送給DisplayTag。

  3. DisplayTag實作分頁。

這裡有一個很奇怪的部份是,假設我們的資料是1000筆,但每一頁顯示是10筆,所以會變成:

DisplayTag因為只需要顯示10筆資料,所以它會把顯示的10筆取出來後,把剩下的990筆資料捨棄,而使用者跳到第二頁時,程式會再重新撈出1000筆資料後,DisplayTag再取需要的10筆資料,而捨棄不需要的990筆。

這個當然不是DisplayTag的希望,問題是出在Appfuse,因為它並沒有按照第三方的DisplayTag規範來實作,所以我們必須幫我們的範本程式,把這些程式補上。

下方我們以「查看用戶」的功能來實作。

  1. 繼承org.displaytag.pagination.PaginatedList。

org.displaytag.pagination.PaginatedList是一個Interface,原本是要實作它,但是因為它沒有宣告排序的功能,所以為了彌補這個部份,我們宣告一個Interface ExtendedPaginatedList 繼承PaginatedList,並放在package com.mycompany.mytest.util裡。

import org.displaytag.pagination.PaginatedList;

import org.displaytag.properties.SortOrderEnum;

import java.util.List;

public interface ExtendedPaginatedList extends PaginatedList {

   /** Request params as constants.  */

   public interface IRequestParameters{

       String SORT = "sort";

       String PAGE = "page";

       String ASC = "asc";

       String DESC = "desc";

       String DIRECTION = "dir";

   }

 

   /** Set the default page size **/

   int DEFAULT_PAGE_SIZE = 1;

 

   /** set results list */

   void setList(List resultList);

 

   /**  Set the Total - total number of records or rows (e.g 10,000 rows found with the query) **/

   void setFullListSize(int total);

 

   /**  set the Page Size - to display the required number of rows (e.g 25 rows out of 10,000)  **/

   void setPageSize(int pageSize);

 

   /** Set the Index - start with 0 and keep increamenting  **/

   void setIndex(int index);

 

   /** get the first record index **/

   int getFirstRecordIndex();

 

   int getPageNumber();

   

   /**  get page size **/

   int getObjectsPerPage();

   

   int getTotalPages();

   

   int getFullListSize();

 

   /**  Set the sort Direction  -  asc or dsc **/

   void setSortDirection(SortOrderEnum sortOrderEnum);

 

   /** set sort criterion **/

   void setSortCriterion(String sortCriterion);

 

}

 

  1. 實作ExtendedPaginatedList.java。

再來我們要實作剛剛宣告的Interface,程式碼如下,一樣放在package com.mycompany.mytest.util裡:

import javax.servlet.http.HttpServletRequest;

import org.displaytag.properties.SortOrderEnum;

import java.util.List;

 

/**

* <code>com.gorti.project.web.ui.action.PaginatedListImpl</code> implemnts

* </code>com.gorti.project.web.ui.action.IExtendedPaginatedList</code> This

* class can be used for pagination purpose. This class depends upon

* HttpServletRequest object. To be used by Controllers in case of Http

* requests.

*

* @author

*/

public class PaginatedListImpl implements ExtendedPaginatedList {

 

/** current page index, starts at 0 */

private int index;

 

/** number of results per page (number of rows per page to be displayed ) */

private int pageSize;

 

/** total number of results (the total number of rows ) */

private int fullListSize;

 

/** list of results (rows found ) in the current page */

private List list;

 

/** default sorting order */

private SortOrderEnum sortDirection = SortOrderEnum.ASCENDING;

 

/** sort criteria (sorting property name) */

private String sortCriterion;

 

/** Http servlet request * */

private HttpServletRequest request;

 

/** default constructor * */

public PaginatedListImpl() {

}

 

/**

* Create <code>PaginatedListImpl</code> instance using the

* <code>HttpServletRequest</code> object.

*

* @param request

*        <code>HttpServletRequest</code> object.

*/

/**

* Create <code>PaginatedListImpl</code> instance using the

* <code>HttpServletRequest</code> object.

*

* @param request

*        <code>HttpServletRequest</code> object.

* @param pageSize

*        the page size - the total number of rows per page.

*/

public PaginatedListImpl(HttpServletRequest request, int pageSize) {

sortCriterion = request.getParameter(ExtendedPaginatedList.IRequestParameters.SORT);

sortDirection = ExtendedPaginatedList.IRequestParameters.DESC.equals(request.getParameter(ExtendedPaginatedList.IRequestParameters.DIRECTION)) ? SortOrderEnum.DESCENDING

: SortOrderEnum.ASCENDING;

pageSize = pageSize != 0 ? pageSize : DEFAULT_PAGE_SIZE;

String page = request.getParameter(ExtendedPaginatedList.IRequestParameters.PAGE);

index = page == null ? 0 : Integer.parseInt(page) - 1;

}

 

/**

* Create <code>PaginatedListImpl</code> instance .

*

* @param pageSize

*        the page size - the total number of rows per page.

* @return <code>ExtendedPaginatedList</code> instance.

* @throws Exception

*         -

*         problem while creating paginatedlist object.

*/

public ExtendedPaginatedList getPaginatedListObject(int pageSize) throws Exception {

 

if (request == null) {

throw new Exception("Cannot create paginated list. Depends upon HttpServletRequest.");

}

return new PaginatedListImpl(request, pageSize);

}

 

/**

* Set the non-null <code>HttpServletRequest</code> object.

*

* @param request

*        a <code>HttpServletRequest</code> object.

*/

public void setRequest(HttpServletRequest request) {

this.request = request;

}

 

public int getFirstRecordIndex() {

return index * pageSize;

}

 

public int getIndex() {

return index;

}

 

public void setIndex(int index) {

this.index = index;

}

 

public void setPageSize(int pageSize) {

this.pageSize = pageSize;

}

 

public List getList() {

return list;

}

 

public void setList(List results) {

this.list = results;

}

 

public int getFullListSize() {

return fullListSize;

}

 

public void setFullListSize(int fullListSize) {

this.fullListSize = fullListSize;

}

 

public int getTotalPages() {

return (int) Math.ceil(((double) fullListSize) / pageSize);

}

 

public int getObjectsPerPage() {

return pageSize;

}

 

public int getPageNumber() {

return index + 1;

}

 

public String getSearchId() {

// Not implemented for now.

// This is required, if we want the ID to be included in the paginated

// purpose.

return null;

 

}

 

public String getSortCriterion() {

return sortCriterion;

}

 

public SortOrderEnum getSortDirection() {

return sortDirection;

}

 

public void setSortCriterion(String sortCriterion) {

this.sortCriterion = sortCriterion;

}

 

public void setSortDirection(SortOrderEnum sortDirection) {

this.sortDirection = sortDirection;

}

 

}

  1. 再來我們要生一個Factory來控管PaginateList,還是放在package com.mycompany.mytest.util裡。

import javax.servlet.http.HttpServletRequest;

import org.displaytag.properties.SortOrderEnum;

import org.springframework.stereotype.Service;

@Service("paginateListFactory")

public class PaginateListFactory {

   private static final int DEFAULT_PAGE_SIZE = 10;

 

public ExtendedPaginatedList getPaginatedListFromRequest(HttpServletRequest request) {

 

       ExtendedPaginatedList paginatedList = new PaginatedListImpl();

       String sortCriterion = null;

       String thePage = null;

       if (request != null) {

           sortCriterion = request.getParameter(ExtendedPaginatedList.IRequestParameters.SORT);

           paginatedList.setSortDirection(ExtendedPaginatedList.IRequestParameters.DESC.equals(request.getParameter(ExtendedPaginatedList.IRequestParameters.DIRECTION)) ? SortOrderEnum.DESCENDING: SortOrderEnum.ASCENDING);

           thePage = request.getParameter(ExtendedPaginatedList.IRequestParameters.PAGE);

        }

       paginatedList.setSortCriterion(sortCriterion);

       paginatedList.setPageSize(DEFAULT_PAGE_SIZE);

       

       if (thePage != null) {

           int index = paginatedList == null ? 0: Integer.parseInt(thePage) - 1;

           paginatedList.setIndex(index);

       } else {

           paginatedList.setIndex(0);

       }

 

       return paginatedList;

   }

}

這邊有二點要注意的,一是DEFAULT_PAGE_SIZE=10,也就是說我們預設每一頁是10筆資料,第二點是@Service("paginateListFactory"),我們有設定這個Class是一個Service,所以預計它會被Spring的<context:component-scan base-package="com.xxx"/>(這段程式在applicationContext.xml裡)掃瞄到,所以要確認package是正確可被掃瞄到的;另外,為了方便稍候的測試,我們先將DEFAULT_PAGE_SIZE改為2

  1. 在Action中宣告並呼叫PaginateListFactory與ExtendedPaginatedList。

因為預定是大部份的Action中都會用到的內容,所以我們把下方這段Code加在BaseAction中。

protected PaginateListFactory paginateListFactory;

public PaginateListFactory getPaginateListFactory() {
if (null == paginateListFactory) {
paginateListFactory = (PaginateListFactory) getApplicationContext().getBean("paginateListFactory");
}
return paginateListFactory;
}

public void setPaginateListFactory(PaginateListFactory paginateListFactory) {
this.paginateListFactory = paginateListFactory;
}

protected ExtendedPaginatedList getPaginatedList() {

return getPaginateListFactory().getPaginatedListFromRequest(getRequest());

}

protected ApplicationContext getApplicationContext() {

ServletContext sc = getRequest().getSession().getServletContext();

return WebApplicationContextUtils.getRequiredWebApplicationContext(sc);

}

這樣基本的準備就完成了,再來要實作分頁功能。

arrow
arrow
    創作者介紹
    創作者 JAVA Programmer 的頭像
    JAVA Programmer

    台灣的Web工程師

    JAVA Programmer 發表在 痞客邦 留言(0) 人氣()