功能強大的 eXtreme Table 使用

eXtreme Table 說明 

eXtreme Table 是ExtremeCompontents(http://extremecomponents.orghttp://sourceforge.net/projects/extremecomp/)中一個功能強大而又容易配置、擴展、自定義的Table控件,其功能包括分頁、排序、過濾、導出Excel、pdf和彙總等。 

擴展eXtreme Table:extremetable-ext.jar是我們自己編寫的eXtreme Table擴展包,裏面的類繼承了原eXtreme Table中的類,並根據我們自己的需要進行了修改和擴展。主要擴展內容包括:顯示分頁頁號、CSV導出表頭等。其樣子類似這樣: 


基本配置: 

1)首先下載發行包 http://sourceforge.net/projects/extremecomp
2)將包內的extremecomponents.jar 文件拷貝到項目的 WEB-INF/lib 目錄中 
3)將 images 文件夾拷貝到 webroot目錄中 
4)將 extremecomponents.css 拷貝到 webroot/css目錄中 
5)將eXtreme Table擴展包extremetable-ext.jar拷貝到項目的 WEB-INF/lib 目錄中 
6)eXtremeTable支持在properties文件裏方便的統一配置豐富的全局屬性,可以在/source/org/extremecomponents/table/core目錄找到extremetable.properties文件,可以把它複製到src/裏面並進行修改,也可以在src/裏新建一個extremetable.properties文件,在裏面只寫需要修改的屬性,其他屬性會自動去jar包中的extremetable.properties文件獲取。 

還要在web.xml中加上: 

<context-param>	
	<param-name>extremecomponentsPreferencesLocation</param-name>
        <param-value>/extremetable.properties</param-value>	
</context-param>	
<filter>			
	<filter-name>eXtremeExport</filter-name>		
	<filter-class>org.extremecomponents.table.filter.ExportFilter</filter-class>		
</filter>			
<filter-mapping>			
	<filter-name>eXtremeExport</filter-name>		
	<url-pattern>/*</url-pattern>		
</filter-mapping>

本項目用到的一些extremetable.properties配置:

table.filterable=false	 不允許過濾 
table.sortable=false	 不允許排序 
table.imagePath=/images/table/*.gif	 圖片路徑	
table.locale=ja_JP	 使用日語	

table.view.html=org.extremecomponents.table.view.UserCompactView	 使用extremetable-ext中的html視圖類 
export.view.csv=org.extremecomponents.table.view.UserCsvView	 使用extremetable-ext中的CSV視圖類 

row.highlightRow=true	 鼠標經過時高亮顯示行	

column.format.date=yyyy-MM-dd HH:mm:ss	 當列設置爲cell="date"時採用的顯示格式	
column.format.currency=###,###,###,###,#00.00	 當列設置爲cell="currency"時採用的顯示格式	

table.pageDisplayed=7	 在頁號選擇中顯示7個頁號	 (如圖中1所示位置)	
table.rowsDisplayed=20	 表格每頁顯示20行

基本原理和流程: 

1、首先,從action中按指定的每頁n行獲取第一頁的數據,即獲取前n個數據。 
2、Action將數據發給JSP頁面,由eXtremeTable的<ec:table>標籤顯示出第一頁。 
3、JSP中的<ec:table>本質上是一個form,在選擇其他頁時,eXtremeTable將把上次傳入的參數加上要顯示的頁號等參數作爲該form的參數,把該form提交給指定的action。 
4、Action將按照傳入的上次檢索條件和本次的頁號等參數重新獲取一遍要顯示的數據,然後再發給JSP中的<ec:table>。每次只取得一頁顯示需要的結果集,不獲取多餘的數據,從而減輕了數據庫的負荷。 

使用Limit特性: 

  默認的情況下eXtremeTable取得所有的結果集然後處理Beans集合,這樣的好處是你可以隨意進行排序、過濾和分頁操作。你只需要組裝Beans集合並讓eXtremeTable知道如何引用它。這樣的操作對於小到中等數據量的結果集非常有效,但結果集很大時這將非常糟糕。爲了提高性能,正如前面基本原理和流程所描述的,我們希望每次只取得一頁顯示需要的結果集,不獲取多餘的數據,即數據庫端分頁的方案。爲此我們使用eXtremeTable的Limit特性。 
  Limit這個名字來自MySQL的limit命令,Limit接口的目的就是如何對錶的結果集進行limit處理。Limit實現知道當排序、過濾、分頁、導出時,用戶如何與表互相作用。有了這些信息你將能夠使用可能是最有效的方式顯示正確的過濾、排序、分頁後的請求頁面。 
  使用Limit時,eXtremeTable會使用Limit對象向Action傳遞PageNo,PageSize,OrderBy等分頁信息。而服務端將向EC返回總記錄數和當前頁的內容。

基本用法:

下面以一個簡單的例子說明最基本的用法:

1) JSP中:

  一個簡單的eXtreme Table類似於這個樣子:
<ec:table items="operators" var="operator"	
		action="${pageContext.request.contextPath}/sample.do"
		retrieveRowsCallback="limit" sortRowsCallback="limit" filterRowsCallback="limit"
		filterable="false" sortable="false" showExports="true"
		autoIncludeParameters="${empty param.autoInc?true:false}">			
		<ec:exportCsv fileName="DepositHistory.csv" tooltip="CSV Download" />			
		<ec:row>			
			<ec:column property="csLastName" title="名前" />		
			<ec:column property="csId" title="CS_ID" />		
			<ec:column property="csGroupId" title="権限グループ" />		
			<ec:column property="updateDate" cell="date" title="更新日付" />		
		</ec:row>			
	</ec:table>
        該表格從集合operators中獲取每行的元素,賦值給變量operator,用作每行處理的數據。

        下面說明各項屬性:

        <ec:table>標籤:

items="operators" 按page、request、session和application範圍的順序搜索並遍歷集合operators,從中迭代獲取數據 
var="operator" 把每次從集合operators中取出的單個元素賦值給名爲operator的bean,存放在page範圍中
action="${pageContext.request.contextPath}/sample.do"指定處理此表單的Action 
retrieveRowsCallback="limit" 指定檢索Callback使用LimitCallback。爲了使用Limit特性,eXtremeTable需要使用limit特定的RetrieveRowsCallback
sortRowsCallback="limit" 指定排序Callback使用LimitCallback。爲了使用Limit特性,eXtremeTable需要使用limit特定的SortRowsCallback
filterRowsCallback="limit" 指定過濾Callback使用LimitCallback。爲了使用Limit特性,eXtremeTable需要使用limit特定的FilterRowsCallback
filterable="false" 設定可否過濾(因爲extremetable.properties已經進行了設置,所以本例中此處其實不用設置此屬性)
sortable="false" 設定可否排序(因爲extremetable.properties已經進行了設置,所以本例中此處其實不用設置此屬性)
showExports="true" 設定是否顯示導出功能 (默認爲true,所以本例中其實可以不寫此項)
autoIncludeParameters="${empty param.autoInc?true:false}"設定是否包含參數,設置爲true時,它會把你上次傳過來的參數自動生成爲ec form的hidden input, 這好處是在查詢的時候,使每次翻頁的查詢參數都是相同的。 
注:其中,autoIncludeParameters之所以設置成${empty param.autoInc?true:false},是爲了更靈活地控制是否包含上次傳過來的參數——當你不希望它包含上次傳過來的參數時,只要在傳過來的參數中加上一條autoInc=false。比方說,你在ec form中提供了一列checkbox控件用來指定要刪除的記錄,如果你只是簡單地把autoIncludeParameters設置成了true,就會帶來一個問題:如果第一次刪除了N18, 等二次刪除N9的時候,因爲N18被auto include進ec form作爲參數了,所以會同時刪除 N18和N9。而N18此時已經不存在了,於是就會導致執行第二次刪除的時候失敗。解決辦法就是進行刪除操作的時候加多一個參數autoInc=false,並且在<ec:table>中設置autoIncludeParameters="${empty param.autoInc?true:false}",則刪除時就不會把參數帶到下一次了。
        <ec:exportCsv>標籤:提供CSV導出功能,可以把表格中的數據導出
fileName 設置導出的目標文件名
tooltip 設置鼠標懸浮時顯示的提示文字
其他的導出標籤還有:
<ec:exportXls> xls導出功能 
<ec:exportPdf> pdf導出功能 
        其中的屬性與<ec:exportCsv>標籤相同。
        <ec:row>標籤:<ec:row>和</ec:row>括來的內容就是每行中顯示的內容
        <ec:column>標籤:設置行中的每個列,即單元格
property="updateDate" 從page範圍中取得名爲operator的bean,並得到它對應的updateDate屬性值。如果你正使用 Beans集合請確認具有對應的getter方法;如果使用Maps集合則不需要任何別的動作, eXtremeTable能夠通過屬性名從Map中得到對應的值。 
cell="date" 使用date格式,即extremetable.properties中設置的column.format.date 
title="更新日付" 設置表頭,即列標題 
其他常用屬性:
alias alias(別名)屬性用來唯一地標識這列。當同樣的屬性被多列使用時用來唯一地標識一列。 
viewsAllowed viewsAllowed屬性指定類允許使用的視圖。視圖包括:html、pdf、xls、csv,以及任何定製的視圖。 如果你指定一個或幾個視圖,那麼列僅能使用這些指定的視圖。例如:你指定viewsAllowed="pdf",這意味着這列只允許PDF導出,而不能進行其他格式的導出或html視圖。 
viewsDenied viewsDenied屬性指定類不允許使用的視圖。視圖包括:html、pdf、xls、csv,以及任何定製的視圖。 如果你指定一個或幾個視圖,那麼列僅這些指定的視圖不能被使用。例如:你指定viewsDenied="html",這意味着這列不允許使用html試圖,但能進行任何形式的導出。 

2) Action中:

  前面JSP中已經指明瞭使用Limit特性。下面在Action中也需要增加一些關於Limit的語句。
  首先需要創建一個Limit。
  本項目中已經把提供了現成Limit的獲取方法,位於cn.bestwiz.jhf.admin.common.page.ExtremeTablePage方法中。
  一般用這麼一條語句即可獲得所需的Limit對象:Limit limit = ExtremeTablePage.getLimit(request);
  本例中的相關Action語句如下:
SampleService sampleService = new SampleService();		
		//ExtremeTable分頁
		Limit limit = ExtremeTablePage.getLimit(request);  //獲取得所需的Limit對象
		Page etpage = sampleService.getOperatorList(limit.getPage(), limit.getCurrentRowsDisplayed());  //向Service方法傳入要顯示的頁號limit.getPage()和每頁的行數limit.getCurrentRowsDisplayed(),以實現數據庫端分頁查詢
		//返回ExtremeTable分頁結果
		request.setAttribute("operators", etpage.getResult());  //把要顯示的結果集etpage.getResult()傳給JSP,其中的operators就是JSP的<ec:table>標籤中items="operators"屬性定義的變量名
		request.setAttribute("totalRows", etpage.getTotalCount());  //把總記錄數(即總行數)etpage.getTotalCount()傳給JSP,其中totalRows是eXtremeTable內定的總行數的變量名,不可隨意更改。
        其中,Page是本項目中自定義的一個類,是爲了方便分頁處理,它把分頁所需的各項參數都封裝到了一個類裏,使得用起來更加方便。

3) Service中:

  從前面Action部分的
Page etpage = sampleService.getOperatorList(limit.getPage(), limit.getCurrentRowsDisplayed());
        我們已經看到,對應的Service方法需要接受兩個傳入的參數:要顯示的頁號、每頁的行數。所以本例中對應的Service方法應該是類似這樣的:
public Page getOperatorList(int pageNo, int pageSize) throws ServiceException {		
		Page page = null;	
		……	
		try {	
			DbSessionFactory.beginTransaction(DbSessionFactory.INFO);
			……
			SampleDao sampleDao = new SampleDao();
			page = sampleDao.getOperatorList(pageNo, pageSize, null);
			……
			DbSessionFactory.commitTransaction(DbSessionFactory.INFO);
		} catch ……	
		……	
		return page;	
	}
        其中,pageNo是要顯示的頁號、pageSize是每頁的行數,在Service中只要把傳入的這兩個參數忠實地傳給Dao方法就行了,不必也不應進行任何處理。
  總的來說,Service中的變化一共只有三處:
1、返回值爲Page類型
2、傳入的參數多了int pageNo, int pageSize兩項
3、在調用Dao方法時,要把pageNo和pageSize兩個參數傳過去
  除此之外,不用做任何其他改變。

4) Dao中:

  從前面Service部分的
page = sampleDao.getOperatorList(pageNo, pageSize, null);
        我們已經看到,對應的Dao方法需要接受兩個傳入的參數:要顯示的頁號pageNo、每頁的行數pageSize。所以本例中對應的Dao方法應該是類似這樣的:
public class SampleDao extends BaseHibernateDao {  //因爲要用到分頁查詢,所以必須繼承自BaseHibernateDao	
		public SampleDao(){
			this.setSession(DbSessionFactory.infoSession());  //設置要使用的數據庫	
		}		
		……		
		public Page getOperatorList(int pageNo, int pageSize, Object[] args){ //其中Object[] args是參數數組,用於往hql語句中傳參		
			……	
			String hql = "from JhfCsOperator";  //構建一個HQL語句	
			……	
			try {	
				……
				Page page = pagedQuery(hql, pageNo, pageSize, args);  //進行分頁查詢。
				……
			} catch ……	
			……	
			return page;	
		}		
		……		
	}
        其中pagedQuery方法是BaseHibernateDao中定義的方法,用於分頁查詢。該方法接受HQL語句、頁號、每頁大小以及傳入hql語句的參數數組這四個參數,執行相應的查詢,然後返回Page對象。至此,本例就完成了。

更復雜的應用:

1) 設定初始每頁行數:

  默認情況下,初始每頁行數就是extremetable.properties中的table.rowsDisplayed屬性值。
  如果想要自定義某個表的初始每頁行數(假設爲10),需要如下操作: 
1、JSP中: 
在<ec:table>標籤中設置屬性 
rowsDisplayed="10" 
這樣在JSP中顯示時就將以10作爲初始的每頁行數來顯示。 
2、Action中: 
因爲運行時的流程是先到Action,然後再轉到JSP,所以當第一次進入Action時,並不能得到JSP中設置的任何參數,所以上一條中設置的rowsDisplayed無法影響到Action第一次的查詢動作。以本例來說,雖然在JSP中設置了rowsDisplayed="10",但是Action在第一次獲取結果集時仍將按照extremetable.properties中設置的默認20行來查詢,雖然在JSP頁面中能夠按照10行來顯示,但剩下的10條數據就成了冗餘數據了。而如果JSP中設置了rowsDisplayed="30",Action在第一次獲取結果集時仍將只查詢20行,這樣顯示的時候就會出問題了。
所以必須在Action中設置初始每頁行數。 
爲此,只要把上面的 
Limit limit = ExtremeTablePage.getLimit(request);
改成

Limit limit = ExtremeTablePage.getLimit(request, 10);  //其中10就是初始每頁行數
即可。其他部分都不需要修改,Service和Dao也不需要修改。
另外,爲了便於以後維護,建議僅在一個地方定義此參數,具體做法可以類似下面這樣(僅供參考):
Action中:
int pageSize = 10;  //以後要改的話只須改這一個地方
Limit limit = ExtremeTablePage.getLimit(request, pageSize);
request.setAttribute("pageSize", pageSize);
JSP的<ec:table>標籤中:
rowsDisplayed="${pageSize}" 

2) 在同一頁面中使用多個eXtremeTable

  要在同一JSP頁面中互不干擾地使用兩個或多個不同的eXtremeTable,必須進行一些特別的設置:
1、JSP中:
在每個<ec:table>標籤中設置屬性 tableId ,爲每個表格設置一個ID,例如:
tableId="table1"
這個ID將在其他各項操作中唯一地標識這個表。
2、Action中:
Action中需要把前面示例中的相關各句如下修改:
SampleService sampleService = new SampleService();
			//ExtremeTable分頁
			Limit limit = ExtremeTablePage.getLimit(request, "table1");  //指明對應的tableId
			Page etpage = sampleService.getOperatorList(limit.getPage(), limit.getCurrentRowsDisplayed());  //這句不變
			//返回ExtremeTable分頁結果
			request.setAttribute("operators", etpage.getResult());  //這句不變
			request.setAttribute("table1_totalRows", etpage.getTotalCount());  //把屬性名由原來的 totalRows 改成 tableId + "totalRows"
Service和Dao都不需要修改。
這樣,只要給不同的表格設置不同的tableId,就可以互不干擾地使用了。
注:ExtremeTablePage.getLimit方法還有一個形式:ExtremeTablePage.getLimit(HttpServletRequest request, String tableId, int defautPageSize) ,可以同時傳入這三個參數。

3) 把eXtremeTable嵌套在其他form中

  有時需要把eXtremeTable嵌入到其他form中,作爲其他form的一部分來使用和提交。但是默認情況下eXtremeTable本身就是一個form(就是說<ec:table>標籤最終會生成<form>標籤),所以不能直接嵌套。如果你想在表體中包含一些定製的form元素, 或者想將eXtremeTable嵌入到另外的form中,那麼你就要使用表標籤的form屬性用來參照最近的form。
  例如,如果在<ec:table>標籤中設置了屬性 form="form1"
  那麼<ec:table>將不再生成<form></form>標籤,只生成表中的其他內容,這樣只要把eXtremeTable放在name="form1"的form中,eXtremeTable中的所有內容都將作爲form1的一部分來顯示和提交。
  在Struts框架中,<html:form>標籤生成的form,其name值爲其action定義的name。
  例如,如果struts-config.xml中定義了
<action path="/currencypair" name="currencyPairForm"		
			validate="false" scope="request"
			type="cn.bestwiz.jhf.admin.system.action.CurrencyPairAction">
        那麼JSP中 
<html:form action="currencypair.do"> 
最終生成的form的name就等於currencyPairForm。如果要把eXtremeTable嵌套到該form中,就要在<ec:table>中設置form = "currencyPairForm",並把整個<ec:table> </ec:table>塊放到<html:form action="currencypair.do"> </html:form>塊內。

本文排版稍有改動,便於查閱,原文地址:http://www.iteye.com/topic/832612#

功能強大的 eXtreme Table 使用 http://blog.csdn.net/hobbypei/article/details/6722488

附:

相關教程:https://code.google.com/p/extremetable/wiki/Tutorials

eXtremeComponents參考文檔 http://www.blogjava.net/lucky/articles/33380.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章