<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    lyyb2001

    只是為方便自己找記錄而已
    posts - 57, comments - 27, trackbacks - 0, articles - 5
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 ::  :: 管理

    eXtremeComponents指南

    Posted on 2008-03-04 22:19 skycity 閱讀(599) 評(píng)論(0)  編輯  收藏 所屬分類: J2EE技術(shù)

    定制FilterCell


    1.?引言

    列的filterCell屬性控制過濾器如何顯示,它和cell屬性非常相像并且也是實(shí)現(xiàn)Cell接口。馬上要定義的是默認(rèn)的和droplist這兩個(gè)過濾器cells。 默認(rèn)的是一個(gè)輸入框元素而droplist是一個(gè)下拉列表元素。當(dāng)然,如果你需要進(jìn)行一些定制你可以插接自己的實(shí)現(xiàn)。

    最近,我被問到是否能夠?qū)崿F(xiàn)一個(gè)過濾器cell,顯示已經(jīng)通過別的過濾器過濾得到數(shù)據(jù)子集。答案當(dāng)然是肯定的,而且這是我將在這里示范的。通常定制的 cell可以很容易被創(chuàng)建,這個(gè)示例將印證這點(diǎn)。在這個(gè)示例里last name列里顯示的將是通過first name過濾后的子集。如果沒有通過 first name過濾那么所有值都將被顯示。

    1.1.?定制Droplist過濾器Cell示例

    通常你只需要為過濾器cell實(shí)現(xiàn)Cell接口。然而,因?yàn)槲覀円獎(jiǎng)?chuàng)建的過濾器cell是一個(gè)下拉列表,我們可以通過擴(kuò)展 FilterDroplistCell來獲得它已經(jīng)提供的很多功能,F(xiàn)ilterDroplistCell是發(fā)行包已經(jīng)提供的cells之一。

    我們需要覆蓋FilterDroplistCell的唯一方法是getFilterDropList()。這是整個(gè)類的全部代碼:

    public class FilteredDroplistCell extends FilterDroplistCell {
    private static Log logger = LogFactory.getLog(FilterDroplistCell.class);

    protected List getFilterDropList(TableModel model, Column column) {
    List droplist = new ArrayList();

    String firstNameFilter = model.getLimit().getFilterSet().getValue("firstName");

    Collection beans = model.getCollectionOfBeans();
    for (Iterator iter = beans.iterator(); iter.hasNext();) {
    Object bean = iter.next();
    try {
    String firstName = BeanUtils.getProperty(bean, "firstName");
    if (StringUtils.isNotBlank(firstNameFilter) && !firstName.equals(firstNameFilter)) {
    continue;
    }

    String lastName = BeanUtils.getProperty(bean, column.getProperty());
    if ((lastName != null) && !droplist.contains(lastName)) {
    droplist.add(lastName);
    }
    } catch (Exception e) {
    logger.debug("Problems getting the droplist.", e);
    }
    }

    Collections.sort(droplist);

    return droplist;
    }
    }

    如果你比較這個(gè)類和父類,你會(huì)發(fā)現(xiàn)它們只有微小的區(qū)別。

    首先需要注意的是我們需要找出first name是否已經(jīng)被過濾了。

    String firstNameFilter = model.getLimit().getFilterSet().getValue("firstName");

    然后我們需要判斷當(dāng)前bean的first name值是否和first name過濾器值相同。如果相同,將當(dāng)前的last name值 添加到droplist中。

    String firstName = BeanUtils.getProperty(bean, "firstName");
    if (StringUtils.isNotBlank(firstNameFilter) && !firstName.equals(firstNameFilter)) {
    continue;
    }

    如果last name將添加到droplist中,我們需要檢查droplist中是否已經(jīng)包含了這個(gè)值。如果沒有,我們就把它添加到droplist中。

    String lastName = BeanUtils.getProperty(bean, column.getProperty());
    if ((lastName != null) && !droplist.contains(lastName)) {
    droplist.add(lastName);
    }

    為了使用這個(gè)Cell你應(yīng)該在Preferences中聲明一個(gè)別名。 當(dāng)然,你可以省略這步而在JSP中提供這個(gè)Cell實(shí)現(xiàn)類的全路徑,但是使用Preferences更簡(jiǎn)潔。

    column.filterCell.filteredDroplist=org.extremesite.cell.FilteredDroplistCell

    在ColumnTag通過設(shè)置filterCell屬性來使用FilteredDroplistCell。

    <ec:column property="lastName" filterCell="filteredDroplist"/>

    如果不清楚Preferences和ColumnTag定義語法請(qǐng)參考Preferences指南。

    定制FilterRowsCallback


    1.?引言

    FilterRowsCallback被用來過濾傳給eXtremeTable的Beans的Collection。 FilterRowsCallback的默認(rèn)實(shí)現(xiàn)是得到Beans或Maps的Collection,然后通過實(shí)現(xiàn)jakarta Predicate接口來進(jìn)行過濾。當(dāng)然,如果你需要進(jìn)行一些定制你可以插接自己的實(shí)現(xiàn)。

    首先聲明,本示例代碼包含一些從原包中剪切、粘貼的代碼(雖然不是很多)。在 最初的最終發(fā)行包之后,值過濾得到進(jìn)一步改善使得更具復(fù)用性并更容易實(shí)現(xiàn),可能和定制cell代碼行數(shù)相同。 當(dāng)然,我被要求并非常樂意示范如何在當(dāng)前代碼基礎(chǔ)上實(shí)現(xiàn)定制過濾。這有非常清晰的hooks實(shí)現(xiàn),并且很容易實(shí)現(xiàn)。

    本示例示范了如何調(diào)整代碼為過濾器提供一個(gè)精確的比較功能。當(dāng)前的實(shí)現(xiàn)是通過使用StringUtils.contains()方法進(jìn)行模糊比較。 本示例將使用StringUtils.equals()方法。你可以按照你的需要來調(diào)整代碼進(jìn)行更多定制。

    1.1.?定制FilterRowsCallback示例

    首先你需要做的是創(chuàng)建一個(gè)實(shí)現(xiàn)Predicate接口的定制類。Predicate要求我們實(shí)現(xiàn)evaluate()方法來判斷是否包含 當(dāng)前bean。因?yàn)槟銉H僅調(diào)整現(xiàn)在已有的功能,首先得到filterPredicate的源代碼(在發(fā)行包的callback包下), 拷貝到你的工程里。然后向下面展示的一樣將 StringUtils.contains()方法修改為StringUtils.equals()方法:

    public final class ExactMatchFilterPredicate implements Predicate {
    private boolean isSearchMatch(String value, String search) {

    ...

    else if (StringUtils.equals(value, search)) {
    return true;
    }

    ...

    }
    }

    然后我們需要實(shí)現(xiàn)和Predicate共同作用的FilterRowsCallback接口。再一次從發(fā)行包的callback包下拷貝ProcessRowsCallback源代碼到你的工程里。 請(qǐng)參照我們創(chuàng)建的定制的ExactMatchFilterPredicate 類來確認(rèn)僅僅實(shí)現(xiàn)了FilterRowsCallback和修改Predicate。

    public class ExactMatchFilterRows implements FilterRowsCallback {
    public Collection filterRows(TableModel model, Collection rows) throws Exception {

    ...

    if (filtered) {
    Collection collection = new ArrayList();
    Predicate filterPredicate = new ExactMatchFilterPredicate(model);
    CollectionUtils.select(rows, filterPredicate, collection);

    return collection;
    }

    ...

    }
    }

    為了使用這個(gè)FilterRowsCallback你應(yīng)該在Preferences中聲明一個(gè)別名。當(dāng)然,你可以省略這步而在JSP中提供這個(gè)FilterRowsCallback實(shí)現(xiàn)類的全路徑,但是使用Preferences更簡(jiǎn)潔。

    table.filterRowsCallback.exactMatch=org.extremesite.callback.ExactMatchFilterRows

    在TableTag通過設(shè)置filterRowsCallback屬性來使用ExactMatchFilterRows。

    <ec:table filterRowsCallback="exactMatch"/>

    如果不清楚Preferences和ColumnTag定義語法請(qǐng)參考Preferences指南。

    Form指南


    1.?引言

    eXtremeTable本質(zhì)上是一個(gè)form組件,所以我假定表被包在form里,所有的功能都被認(rèn)為是對(duì)form元素的操作。如果你想在表體中包含一些定制的form元素, 或者想將eXtremeTable嵌入到另外的form中,那么你就要使用表標(biāo)簽的form屬性用來參照最近的form。

    為了示范form特性,我們要做的工作將分解為JSP,Cell和Controller。

    1.1.?JSP

    下面列出的是checkbox示例的完整代碼。想要強(qiáng)調(diào)的主要事情是表標(biāo)簽form屬性設(shè)置為presForm,它參照被稱為presForm的form元素。

    同時(shí)請(qǐng)注意表標(biāo)簽的autoIncludeParameters屬性。進(jìn)行排序、過濾、分頁(yè)時(shí),默認(rèn)的eXtremeTable將保持所有傳至JSP頁(yè)面的參數(shù)。 這個(gè)特性對(duì)于內(nèi)部其他的form進(jìn)行排序、過濾、分頁(yè)時(shí),用于高效復(fù)制form元素同樣有效。可以設(shè)置 autoIncludeParameters屬性為false來固定它。

    在這個(gè)form使用id屬性是因?yàn)閤htm標(biāo)準(zhǔn)的要求,同時(shí)你也可以使用form的name屬性。

    <form id="presForm" action="<c:url value="selectedPresidentsListedController.run"/>" method="post">

    Enter your name:
    <input
    type="text"
    name="userName"
    style="font-family:verdana,arial,helvetica,sans-serif;font-size:11px;"
    value="<c:out value="${param.userName}"/>"
    />

    <ec:table
    items="presidents"
    action="${pageContext.request.contextPath}/selectedPresidentsController.run"
    view="compact"
    imagePath="${pageContext.request.contextPath}/images/table/compact/*.gif"
    rowsDisplayed="8"
    autoIncludeParameters="false"
    form="presForm"
    >
    <ec:exportPdf
    fileName="output.pdf"
    tooltip="Export PDF"
    headerColor="black"
    headerBackgroundColor="#b6c2da"
    headerTitle="Presidents"
    />
    <ec:row>
    <ec:column
    alias="checkbox"
    title=" "
    width="5px"
    filterable="false"
    sortable="false"
    viewsAllowed="compact"
    cell="selectedPresident"
    />
    <ec:column property="fullName" title="Name"/>
    <ec:column property="nickName" />
    <ec:column property="term" />
    </ec:row>
    </ec:table>

    <input
    type="button"
    name="sel"
    class="button"
    value="List Selected Presidents"
    onclick="document.forms.presForm.submit();"
    />

    <script type="text/javascript">
    function setPresidentState(chkbx) {
    //make sure that always know the state of the checkbox
    if (chkbx.checked) {
    eval('document.forms.presForm.chkbx_' + chkbx.name).value='SELECTED';
    } else {
    eval('document.forms.presForm.chkbx_' + chkbx.name).value='UNSELECTED';
    }
    }
    </script>

    </form>

    1.1.1.?Form特性的技術(shù)說明

    表標(biāo)簽form屬性參照最近的form是你使用這個(gè)特性所必須知道的,為了更好的理解這個(gè)特性,介紹更多的關(guān)于內(nèi)部實(shí)現(xiàn)技術(shù)的細(xì)節(jié)是值得的。

    如果您不特意指定form屬性,eXtremeTable自動(dòng)在表附近包上一個(gè)form。所有表的動(dòng)作例如:排序、過濾、分頁(yè)將自動(dòng)給一些隱藏的input元素賦值,然后提交這個(gè)form到表標(biāo)簽action屬性設(shè)置的Aciton。 這非常有效,除非您想要將自己的form元素設(shè)置到表體,或者想將這個(gè)表放到別的form里。

    表標(biāo)簽form屬性參照最近的form,所有表的動(dòng)作例如:排序、過濾、分頁(yè)將自動(dòng)給一些隱藏的input元素賦值,但是現(xiàn)在 最近form的action屬性將要改變表標(biāo)簽的動(dòng)作。這非常重要,因?yàn)椋寒?dāng)排序、過濾、分頁(yè)時(shí),eXtremeTable能夠從一個(gè)controller得到數(shù)據(jù)集合 ,但是提交這個(gè)form到別的controller來處理這個(gè)form時(shí)需要對(duì)用戶的輸入進(jìn)行處理。然而,這些對(duì)于你使用表標(biāo)簽來說都是透明的。 就像你現(xiàn)在做的那樣簡(jiǎn)單地設(shè)置表標(biāo)簽的action屬性,然后設(shè)置相關(guān)的form到你想提交的位置。

    1.1.2.?Checkbox

    示例的第一列是checkbox。因?yàn)檫@列不需要參照bean的屬性,alias屬性用來唯一地標(biāo)識(shí)這列。你可以使用property 屬性,但是alias屬性使這列如何使用更清楚。alias屬性還被用來當(dāng)同樣的屬性被多列使用時(shí)唯一地標(biāo)識(shí)一列。

    1.1.3.?Custom Cell

    您也許想知道定制的cell是如何通過名稱selectedPresident被參照的(cell="selectedPresident")。這是一個(gè) 對(duì)eXtremeTable的preferences特性更強(qiáng)的使用。所有要做的就是在extremecomponents.properties文件中添加一個(gè)屬性。 請(qǐng)參考Preferences來了解更多的信息

    column.cell.selectedPresident=org.extremesite.cell.SelectedPresidentCell

    column.cell.selectedPresident就是你定義的用來參照這個(gè)cell的名稱。

    當(dāng)然你也可以使用這個(gè)Cell的全名來進(jìn)行參照。

    <ec:column 
    alias="checkbox"
    title=" "
    width="5px"
    filterable="false"
    sortable="false"
    viewsAllowed="compact"
    cell="org.extremesite.cell.SelectedPresidentCell"
    />

    在屬性文件中定義參照更方便,它可以被任何JSP文件引用。如果類名或包名改變的話你只需要對(duì)一個(gè)地方進(jìn)行修改。

    1.1.4.?JavaScript

    JavaScript的setPresidentState()方法被定制cell用來設(shè)置每個(gè)checkbox元素的是否被選中。 設(shè)置一個(gè)隱藏元素的原因是為了獲得瀏覽器的動(dòng)作而不提交沒有選中的checkbox。通過這個(gè)Controller將一直知道一個(gè)元素是否別選中。

    1.2.?Cell

    定制的cell被用來生成checkbox,另外它也創(chuàng)建一個(gè)隱藏元素用來表示這個(gè)checkbox元素是否被選中。 當(dāng)用戶進(jìn)行排序、過濾、分頁(yè)時(shí),被選中的數(shù)據(jù)集合將被放到session里。

    getExportDisplay()方法沒有返回值,因?yàn)橹卫碇恍枰狧tml顯示。

    public class SelectedPresidentCell implements Cell {
    public String getExportDisplay(TableModel model, Column column) {
    return null;
    }

    public String getHtmlDisplay(TableModel model, Column column) {
    HtmlBuilder html = new HtmlBuilder();

    CellBuilder.tdStart(html, column);

    try {
    Object bean = model.getCurrentRowBean();
    String presidentId = BeanUtils.getProperty(bean, "presidentId");

    Collection selectedPresidentsIds = (Collection)model.getContext().getSessionAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS);
    if (selectedPresidentsIds != null && selectedPresidentsIds.contains(presidentId)) {
    html.input("hidden").name("chkbx_" + presidentId).value(SelectedPresidentsConstants.SELECTED).xclose();
    html.input("checkbox").name(BeanUtils.getProperty(bean, "presidentId"));
    html.onclick("setPresidentState(this)");
    html.checked();
    html.xclose();
    } else {
    html.input("hidden").name("chkbx_" + presidentId).value(SelectedPresidentsConstants.UNSELECTED).xclose();
    html.input("checkbox").name(BeanUtils.getProperty(bean, "presidentId"));
    html.onclick("setPresidentState(this)");
    html.xclose();
    }
    } catch (Exception e) {}

    CellBuilder.tdEnd(html);

    return html.toString();
    }
    }

    1.3.?Controller

    提示:Spring框架的Controller和Struts框架的Action非常相像。

    當(dāng)在另外的form中使用eXtremeTable時(shí),你可能有1個(gè)或2個(gè)controllers。當(dāng)form被提交時(shí),你需要一個(gè)controller 來處理用戶的輸入并重新定向到另外的JSP頁(yè)面。當(dāng)排序、過濾、分頁(yè)時(shí),你可能有另外的controller來得到表使用的數(shù)據(jù)集合并重定向會(huì)本頁(yè)。或者你可以在同一個(gè)controller中分別處理。

    checkbox示例里我使用一個(gè)controller來關(guān)聯(lián)表標(biāo)簽的action屬性。我也使用另外一個(gè)controller來關(guān)聯(lián)form元素的動(dòng)作。

    1.3.1.?表標(biāo)簽動(dòng)作Controller

    這個(gè)controller負(fù)責(zé)調(diào)用SelectedPresidentsUtils來保存被選中的presidentIds到session里并回到同一頁(yè)。

    SelectedPresidentsUtils.saveSelectedPresidentsIDs(request);
    Collection presidents = presidentsService.getPresidents();
    request.setAttribute("presidents", presidents);

    1.3.2.?Form動(dòng)作Controller

    這個(gè)controller負(fù)責(zé)通過presidentIds得到數(shù)據(jù)集并重定向到下一個(gè)Jsp頁(yè)面

    Collection selectedPresidentsIds = SelectedPresidentsUtils.saveSelectedPresidentsIDs(request);
    Collection selectedPresidents = SelectedPresidentsUtils.getSelectedPresidents(presidentsService.getPresidents(), selectedPresidentsIds);
    request.setAttribute("selected", selectedPresidents);
    request.getSession().removeAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS);

    1.3.3.?重新得到Checkbox的值

    我將列出保存presidentIds到session的代碼。我經(jīng)常被問到如何重新得到eXtremeTable中form元素的值。 它的原理是設(shè)置form輸入元素名字屬性值前面加上一些東西來唯一標(biāo)識(shí)元素

    本示例中我關(guān)心的是以chkbx開頭參數(shù)的元素。chkbx后面是唯一的關(guān)聯(lián)到checkbox的presidentId。它被用來判斷這個(gè)checkbox是否別選中。

    public static Collection saveSelectedPresidentsIDs(HttpServletRequest request) {
    Collection presidents = (Collection) request.getSession().getAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS);

    if (presidents == null) {
    presidents = new ArrayList();
    request.getSession().setAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS, presidents);
    }

    Enumeration parameterNames = request.getParameterNames();
    while (parameterNames.hasMoreElements()) {
    String parameterName = (String) parameterNames.nextElement();
    if (parameterName.startsWith("chkbx_")) {
    String presidentId = StringUtils.substringAfter(parameterName, "chkbx_");
    String parameterValue = request.getParameter(parameterName);
    if (parameterValue.equals(SelectedPresidentsConstants.SELECTED)) {
    if (!presidents.contains(presidentId)) {
    presidents.add(presidentId);
    }
    } else {
    presidents.remove(presidentId);
    }
    }
    }

    return presidents;
    }

    Html視圖定制指南


    1.?引言

    eXtremeTable使用View接口來生成HTML。你可以使用發(fā)行包已經(jīng)提供的視圖,或者你可以插入自己的視圖實(shí)現(xiàn)。 現(xiàn)在,創(chuàng)建你自己的視圖相對(duì)比較簡(jiǎn)單,但討論一些設(shè)計(jì)想法和如何著手實(shí)現(xiàn)一個(gè)定制的視圖還是有價(jià)值的。

    我想使創(chuàng)建定制視圖簡(jiǎn)單,但不是想構(gòu)造一個(gè)更復(fù)雜的類似swing的模型,原因是那需要?jiǎng)?chuàng)建大量的對(duì)象來處理對(duì)應(yīng)的內(nèi)部工作。 eXtremeTable以高效為目標(biāo),我也想在視圖的實(shí)現(xiàn)上貫徹這種想法,所以我決定創(chuàng)建一系列的靜態(tài)構(gòu)造器類來實(shí)現(xiàn)分解的最小功能。你可以通過組合這些功能來實(shí)現(xiàn)你的定制視圖。

    學(xué)習(xí)定制視圖的最好途徑是閱讀已經(jīng)存在的視圖的源代碼,修改它來滿足你的需求。如果我示范所有東西的話,這篇指南將變的非常冗長(zhǎng)。取而代之的是我將直接修改默認(rèn)視圖的工具條作為定制視圖的一個(gè)示例。 對(duì)于不同構(gòu)造器的具體細(xì)節(jié)我建議你閱讀源代碼。我也將盡量更新javadocs來提供更好的幫助。

    1.1.?View接口

    實(shí)現(xiàn)View接口的類有3次插入內(nèi)容的機(jī)會(huì)。beforeBody()方法會(huì)被立刻調(diào)用,body()方法在每一行的每一列處理的時(shí)候調(diào)用。 afterBody()方法是被eXtremeTable調(diào)用的最后方法,它將返回代表視圖的一個(gè)對(duì)象。在這個(gè)HTML視圖示例里,它將是一個(gè)字符串。

    public interface View {
    public void beforeBody(TableModel model);
    public void body(TableModel model, Column column);
    public Object afterBody(TableModel model);
    }

    1.2.?Messages示例

    在這篇指南里我將直接修改工具條來實(shí)現(xiàn)這網(wǎng)站上Messages示例的定制視圖。

    public class MessagesView extends AbstractHtmlView { 
    protected void toolbar(TableModel model) {
    TwoColumnTableLayout toolbar = new MessagesToolbar();
    toolbar.layout(getHtmlBuilder(), model);
    }

    protected void statusBar(TableModel model) {
    TwoColumnRowLayout statusBar = new MessagesStatusBar();
    statusBar.layout(getHtmlBuilder(), model);
    }
    }

    這里使用的是默認(rèn)視圖,因此它擴(kuò)展了虛擬視圖來修改工具條和狀態(tài)條。如何修改工具條和(或)狀態(tài)條也是開發(fā)人員問的最多問題。

    默認(rèn)視圖的工具條位于表的上方包括翻頁(yè)鏈接和標(biāo)題。工具條使用TwoColumnTableLayout,它是一個(gè)用于提供在自己表中實(shí)現(xiàn)左右兩列布局的虛擬類。 它將實(shí)現(xiàn)能夠浮在表上方的完美布局。下面就是你需要關(guān)心的虛擬方法,在實(shí)際的html視圖中已經(jīng)為你完成了這個(gè)布局。

    public abstract class TwoColumnTableLayout {
    protected abstract boolean showLayout(TableModel model);
    protected abstract void columnLeft(HtmlBuilder html, TableModel model);
    protected abstract void columnRight(HtmlBuilder html, TableModel model);
    }

    showLayout()方法用來阻止或?qū)е虏季值恼宫F(xiàn)。在我的定制視圖中如果翻頁(yè)或(和)導(dǎo)出顯示那么工具條將展現(xiàn)。

    protected boolean showLayout(TableModel model) {
    boolean showPagination = BuilderUtils.showPagination(model);
    boolean showExports = BuilderUtils.showExports(model);
    if (!showPagination && !showExports) {
    return false;
    }

    return true;
    }

    下面顯示了左列和右列的部分代碼。注意在我的定制視圖中首頁(yè)和前一頁(yè)使用了文字來替代圖片顯示。我真正希望示范的是你需要做的:找到正確的構(gòu)造器類并且僅僅是擴(kuò)展HtmlBuilder的標(biāo)簽。 構(gòu)造器類對(duì)于示范如何找到模型里的信息(以便你能夠做比他們能夠提供的更多的定制工作)也非常有用,。

    protected void columnLeft(HtmlBuilder html, TableModel model) {
    html.td(2).close();
    TableBuilder.title(html, model);
    html.tdEnd();
    }

    protected void columnRight(HtmlBuilder html, TableModel model) {
    boolean showPagination = BuilderUtils.showPagination(model);
    ...
    if (showPagination) {
    html.td(4).close();
    ToolbarBuilder.firstPageItemAsText(html, model);
    html.tdEnd();

    html.td(4).close();
    ToolbarBuilder.prevPageItemAsText(html, model);
    html.tdEnd();
    ...
    }
    ...
    }

    為了使用這個(gè)視圖你需要在Preferences定義一個(gè)別名。 你可以省略這部而在JSP直接給出這個(gè)視圖的完整有效的類名,不過Preferences更為簡(jiǎn)潔。

    table.view.messages=org.extremesite.view.MessagesView

    TableTag也將設(shè)置視圖屬性來使用MessagesView視圖。

    <ec:table view="messages">

    如果不清楚Preferences和TableTag定義語法請(qǐng)參考Preferences指南。

    攔截器使用指南


    1.?引言

    攔截特性被用在運(yùn)行時(shí)需要修改屬性值的時(shí)候,它使得改變基于數(shù)據(jù)的eXtremeTable的行為成為可能。在閱讀擴(kuò)展標(biāo)簽屬性時(shí),你會(huì)發(fā)現(xiàn)它和擴(kuò)展標(biāo)簽屬性具有同樣的概念和方法標(biāo)識(shí)。 區(qū)分使用他們的首要準(zhǔn)則是:如果需要向TLD里已經(jīng)定義的并且能夠在JSP中訪問的標(biāo)簽添加新的屬性時(shí),應(yīng)該使用擴(kuò)展標(biāo)簽屬性;如果僅僅是需要修改已經(jīng)定義好的屬性的值的時(shí)候,應(yīng)該使用攔截器。

    你可能需要了解更多的eXtremeTable如何運(yùn)作的技術(shù)背景才能完全理解這種特性。 eXtremeTable首先做的就是遍歷所有標(biāo)簽并創(chuàng)建對(duì)應(yīng)的模型beans (pojos)。beans是具有和標(biāo)簽一樣屬性,但是使用真實(shí)類型來替換僅僅使用字符串類型的對(duì)象。beans是被模型使用并且是你需要使用攔截特性修改的對(duì)象。 所有的攔截器接口都定義了一個(gè)add方法, add方法被用來處理模型bean第一次創(chuàng)建時(shí)的屬性。行和列的攔截器還有一個(gè)modify 方法。modify方法可以在當(dāng)行和類進(jìn)行處理是對(duì)屬性值進(jìn)行操作。

    1.1.?攔截器列表

    下面列出了具有攔截特性的標(biāo)簽和他們需要被實(shí)現(xiàn)的接口,Bean欄顯示了被模型創(chuàng)建的Bean。

    標(biāo)簽 接口 Bean
    TableTag org.extremecomponents.table.intercept.InterceptTable org.extremecomponents.table.bean.Table
    RowTag org.extremecomponents.table.intercept.InterceptRow org.extremecomponents.table.bean.Row
    ColumnTag org.extremecomponents.table.intercept.InterceptColumn org.extremecomponents.table.bean.Column
    ExportTag org.extremecomponents.table.intercept.InterceptExport org.extremecomponents.table.bean.Export

    1.2.?行攔截器示例

    示范攔截特性的完美示例就是根據(jù)一定的標(biāo)準(zhǔn)來對(duì)行進(jìn)行高亮顯示,這也是我們將要完成的示例。它很短也很簡(jiǎn)單,不過它實(shí)現(xiàn)的概念同樣適用于每一個(gè)攔截器接口。

    我們需要做的第一件事就是實(shí)現(xiàn)InterceptRow接口。你會(huì)注意到這個(gè)接口有兩個(gè)方法:addRowAttributes() 和modifyRowAttributes()。addRowAttributes方法在行bean創(chuàng)建的時(shí)候被調(diào)用, modifyRowAttributes方法在表處理當(dāng)前頁(yè)面行的時(shí)候被調(diào)用。

    public class MarkerIntercept implements InterceptRow {
    public void addRowAttributes(TableModel tableModel, Row row) {
    }

    public void modifyRowAttributes(TableModel model, Row row) {
    President president = (President) model.getCurrentRowBean();
    String career = president.getCareer();
    if (StringUtils.contains(career, "Soldier")) {
    row.setStyle("background-color:#fdffc0;");
    } else {
    row.setStyle("");
    }
    }
    }

    在Preferences里你應(yīng)該定義這個(gè)行攔截器的別名。

    row.intercept.marker=org.extremesite.intercept.MarkerIntercept

    這樣就可以在行標(biāo)簽中使用攔截器MarkerIntercept了。

    <ec:row intercept="marker">

    如果不清楚Preferences和TableTag定義語法請(qǐng)參考Preferences指南。

    Limit指南


    1.?引言

    在你需要處理大量數(shù)據(jù)時(shí)你應(yīng)該考慮使用eXtremeTable的Limit特性。Limit這個(gè)名字來自MySQL的limit 命令,Limit接口的目的就是如何對(duì)表的結(jié)果集進(jìn)行l(wèi)imit處理。Limit實(shí)現(xiàn)知道當(dāng)排序、過濾、分頁(yè)、導(dǎo)出時(shí),用戶如何與表互相作用。有了這些信息你 將能夠使用可能是最有效的方式顯示正確的過濾、排序后的請(qǐng)求頁(yè)面。

    為了示范Limit特性,我將要做的工作將分解為JSP、Controller、Service和DAO。這示范了一種使用分層的方式來處理 Limit。你可以根據(jù)自己的需要來增加或減少層。本示例也使用了Spring框架來重新得到使用Spring的JDBC取得的數(shù)據(jù),因此你的代碼看起來可能有點(diǎn)不同。eXtremeTable的一個(gè)特點(diǎn)就是不依賴任何框架和容器。

    1.1.?JSP

    為了使用Limit特性,eXtremeTable需要使用limit特定的RetrieveRowsCallback、 FilterRowsCallback和SortRowsCallback接口。eXtremeComponents提供了每個(gè)接口的一個(gè)實(shí)現(xiàn),可以簡(jiǎn)單地通過設(shè)置每個(gè)屬性值為limit來簡(jiǎn)單來使用。

    <ec:table 
    items="presidents"
    retrieveRowsCallback="limit"
    filterRowsCallback="limit"
    sortRowsCallback="limit"
    view="limit"
    >
    ...

    另外視圖屬性參照一個(gè)名為limit的定制視圖。這是一個(gè)簡(jiǎn)單修改默認(rèn)eXtremeTable視圖,不包含最后頁(yè)工具條的實(shí)現(xiàn)。這僅僅關(guān)系到你是否能取得確切需要的行。 一些數(shù)據(jù)庫(kù)例如Oracle和MySQL都提供了一種得到確定行的特性,但是,其他的數(shù)據(jù)庫(kù)例如:Sybase沒有提供特性。在我的示例中我考慮最壞的情況你的數(shù)據(jù)庫(kù)不支持這種特性。

    即使你的數(shù)據(jù)庫(kù)不提供取得特定行的特性,當(dāng)你考慮用戶如何和表協(xié)同工作時(shí),Limit仍然非常有意義。用戶通常會(huì)對(duì)一些數(shù)據(jù)進(jìn)行排序、過濾和分頁(yè)。 這個(gè)例子中15條數(shù)據(jù)構(gòu)成一頁(yè),第一頁(yè)需要15條數(shù)據(jù),第二頁(yè)需要30條數(shù)據(jù),第三頁(yè)需要45條數(shù)據(jù),以此類推。在經(jīng)過一段時(shí)間分頁(yè)后,他們常常使用過濾來提煉數(shù)據(jù)。 即使他們不這樣做,他們也必須在此之前對(duì)大量的數(shù)據(jù)進(jìn)行分頁(yè),這將影響效率。當(dāng)然如果允許用戶點(diǎn)擊最后頁(yè),那么所有的數(shù)據(jù)都將被取出,這將非常影響效率。

    1.2.?Controller

    提示:Spring框架的Controller和Struts框架的Action非常相像。

    controller首先需要?jiǎng)?chuàng)建一個(gè)Limit。為了完成這個(gè)你需要得到一些關(guān)于Context和LimitFactory的幫助。

    Context context = new HttpServletRequestContext(request);
    LimitFactory limitFactory = new TableLimitFactory(context);
    Limit limit = new TableLimit(limitFactory);

    Context是一個(gè)處理取得屬性的接口,LimitFactory使用Context來找出用戶如何和eXtremeTable交互。 然后Limit使用LimitFactory來組裝自己。

    為了初始化Limit,它將包含所有的有用的信息。這些信息包括數(shù)據(jù)將被如何排序和過濾,哪一頁(yè)將被顯示和是否允許被導(dǎo)出。

    然而,Limit仍然需要得到行的信息,這樣正確的信息頁(yè)面才能被顯示給用戶。行信息包括開始行、結(jié)束行、當(dāng)前顯示行。 controller必須從service得到這些信息,而Service將從dao中得到這些信息。這里我只給出Controller端的代碼。

    int totalRows = presidentsService.getTotalPresidents(limit.getFilterSet(), limit.isExported());
    limit.setRowAttributes(totalRows, defaultRowsDisplayed);

    limit需要得到所有的行來得到行的信息。service需要知道那些被過濾,不管這些數(shù)據(jù)是否要導(dǎo)出。為了設(shè)置行信息,默認(rèn)的一頁(yè)顯示的行數(shù)需要被設(shè)置。 這可以通過對(duì)TableTag的rowsDisplayed屬性設(shè)置一個(gè)確定的數(shù)值來實(shí)現(xiàn)。

    現(xiàn)在我們只需要從services得到Collection數(shù)據(jù)。

    Collection presidents = presidentsService.getPresidents(limit.getFilterSet(), limit.getSort(), limit.getRowEnd());

    因?yàn)閘imit已經(jīng)包含所有信息,這將十分容易。所有需要做的就是傳入過濾器,排序和最后行的信息。 最后要做的是將Collections和totalRow這些信息傳送回JSP以便eXtremeTable知道如何顯示這些信息。

    request.setAttribute("presidents", presidents);
    request.setAttribute("totalRows", new Integer(totalRows));

    1.3.?Service

    service需要和dao進(jìn)行交互來得到總行數(shù)和Collection。

    1.3.1.?取得總行數(shù)

    controller需要到第一條信息就是總行數(shù)。

    public int getTotalPresidents(FilterSet filterSet, boolean isExported) {
    String totalQuery = presidentsDao.getTotalPresidentsQuery();
    String modTotalQuery = filterQuery(filterSet, totalQuery);
    int totalRows = presidentsDao.getTotalPresidents(modTotalQuery);
    if (isExported && totalRows > maxExportRows) {
    totalRows = maxExportRows;
    }
    return totalRows;
    }

    service和dao一起來過濾結(jié)果集,它的工作方式是在Where語句后面增加更多的AND語句來修改查詢字符串。為此,你需要和Limit FilterSet一起工作。

    FilterSet是一個(gè)過濾器對(duì)象數(shù)組,一個(gè)過濾器包括一個(gè)bean property和這個(gè)過濾器的值。或者,簡(jiǎn)單的說就是用戶想要過濾的行和他們輸入的值。這使得它非常容易交互。service只需要迭代所有的 FilterSet并調(diào)用dao來拼接查詢語句。(譯者注:過濾的實(shí)現(xiàn)方式是:在Where后面增加And語句來改變查詢語句以達(dá)到對(duì)數(shù)據(jù)進(jìn)行過濾的效果)

    private String filterQuery(FilterSet filterSet, String query) {
    if (!filterSet.isFiltered() || filterSet.isCleared()) {
    return query;
    }

    Filter filters[] = filterSet.getFilters();
    for (int i = 0; i < filters.length; i++) {
    Filter filter = filters[i];
    String property = filter.getProperty();
    String value = filter.getValue();
    query = presidentsDao.filterQuery(query, property, value);
    }

    return query;
    }

    query修改包括了filter信息,總行數(shù)。在一些情況下這就足夠,但是當(dāng)用戶導(dǎo)出數(shù)據(jù)時(shí)仍然存在一個(gè)潛在的問題。為了保持高效 service不允許導(dǎo)出超出一個(gè)最大行數(shù)的數(shù)據(jù)。

    1.3.2.?取得Collection

    controller需要到第二條信息就是Collection。

    public Collection getPresidents(FilterSet filterSet, Sort sort, int rowEnd) {
    String patientsQuery = presidentsDao.getPresidentsQuery();
    String modPatientsQuery = filterQuery(filterSet, patientsQuery);
    modPatientsQuery = sortQuery(sort, modPatientsQuery);
    modPatientsQuery = presidentsDao.limitQuery(rowEnd, modPatientsQuery);
    return presidentsDao.getPresidents(modPatientsQuery);
    }

    和前面一樣,service和dao一起來過濾結(jié)果集。

    另外query字符串需要擴(kuò)展ORDER BY語句以便數(shù)據(jù)按照正確的方式進(jìn)行排序。Sort包含一個(gè)bean property和 sortOrder值(正序還是逆序)。service僅僅需要使用Sort來調(diào)用dao。

    private String sortQuery(Sort sort, String query) {
    if (!sort.isSorted()) {
    String defaultSortOrder = presidentsDao.getDefaultSortOrder();
    if (StringUtils.isNotBlank(defaultSortOrder)) {
    return query + defaultSortOrder;
    }

    return query;
    }

    String property = sort.getProperty();
    String sortOrder = sort.getSortOrder();

    return presidentsDao.sortQuery(query, property, sortOrder);
    }

    query字符串最后需要的修改就是增加數(shù)據(jù)庫(kù)特別的指令來limit將要被返回的結(jié)果集。這就是limitQuery() 方法的作用。

    1.4.?DAO

    dao為service負(fù)責(zé)底層數(shù)據(jù)工作。

    1.4.1.?定義Query字符串

    為了真正理解dao,query字符串需要被展示。

    這就是得到數(shù)據(jù)的presidents query字符串:

    private final static String presidentsQuery = 
    " SELECT " +
    " president_id presidentId, " +
    " first_name firstName, " +
    " last_name lastName, " +
    " nick_name nickName, " +
    " concat(first_name, ' ',last_name) fullName, " +
    " term, " +
    " born, " +
    " died, " +
    " education, " +
    " career, " +
    " political_party politicalParty " +
    " FROM presidents ";

    這是得到總行數(shù)的query字符串:

    private final static String totalPresidentsQuery = 
    " SELECT count(*) FROM presidents ";

    1.4.2.?Filter 和 Sort Query 字符串

    兩個(gè)最有趣的方法就是過濾和排序。

    filter看起來像這樣:

    public String filterQuery(String query, String property, String value) {
    StringBuffer result = new StringBuffer(query);

    if (query.indexOf("WHERE") == -1) {
    result.append(" WHERE 1 = 1 "); //stub WHERE clause so can just append AND clause
    }

    if (property.equals("fullName")) {
    result.append(" AND concat(first_name, ' ',last_name) like '%" + value + "%'");
    } else if (property.equals("nickName")) {
    result.append(" AND nick_name like '%" + value + "%'");
    } else {
    result.append(" AND " + property + " like '%" + value + "%'");
    }

    return result.toString();
    }

    filterQuery()方法需要增加正確的AND語句到query字符串。

    sort看起來非常類似:

    public String sortQuery(String query, String property, String sortOrder) {
    StringBuffer result = new StringBuffer(query + " ORDER BY ");

    if (property.equals("fullName")) {
    result.append("concat(first_name, ' ',last_name) " + sortOrder);
    } else {
    result.append(property + " " + sortOrder);
    }

    return result.toString();
    }

    sortQuery()方法需要增加正確的ORDER BY語句到query字符串。

    1.4.3.?Limit Query String

    現(xiàn)在query字符串修改能夠正確的進(jìn)行filter和sort,它還需要修改以便只取頁(yè)面顯示相關(guān)的數(shù)據(jù)。MySQL為s the limit命令。

    public String limitQuery(int rowEnd, String query) {
    return query + " limit " + rowEnd;
    }

    1.4.4.?取回總行數(shù)和Collection.

    service需要的唯一東西就是:總行數(shù)和Collection。

    public Collection getPresidents(final String query) {
    return jdbcTemplate.query(query, new ResultReader() {
    List results = new ArrayList();
    public List getResults() {
    return results;
    }

    public void processRow(ResultSet rs)
    throws SQLException {
    President president = new President();
    president.setPresidentId(new Integer(rs.getInt("presidentId")));
    president.setFirstName(rs.getString("firstName"));
    president.setLastName(rs.getString("lastName"));
    president.setNickName(rs.getString("nickName"));
    president.setFullName(rs.getString("fullName"));
    president.setTerm(rs.getString("term"));
    president.setBorn(rs.getDate("born"));
    president.setDied(rs.getDate("died"));
    president.setEducation(rs.getString("education"));
    president.setCareer(rs.getString("career"));
    president.setPoliticalParty(rs.getString("politicalParty"));
    results.add(president);
    }
    });
    }

    public int getTotalPresidents(final String query) {
    return jdbcTemplate.queryForInt(query);
    }

    ResultReader是一個(gè)幫助處理JDBC查詢的Spring特殊類,作為一個(gè)callback來處理JDBC ResultSet。jdbcTemplate是對(duì)JDBC連接的抽象。

    1.4.5.?默認(rèn)的Sort順序

    最后,這是service需要的默認(rèn)sort順序:

    public String getDefaultSortOrder() {
    return " ORDER BY concat(first_name, ' ', last_name) ";
    }

    Preferences 指南


    1.?引言

    為了設(shè)置全局屬性和設(shè)置,你需要使用Preferences特性,它現(xiàn)在使用一個(gè)屬性文件來實(shí)現(xiàn)。本文檔將很好地介紹如何在web.xml里設(shè)置Preferences, 以及一些需要被定義的通用屬性。在這里我非常樂意介紹一些關(guān)于Preferences的進(jìn)一步用法。

    所有標(biāo)簽屬性表示一個(gè)可插接的接口,它可以通過給出實(shí)現(xiàn)的全路徑來設(shè)置。這為插接實(shí)現(xiàn)提供了一條便利的途徑。當(dāng)然這存在一些為過長(zhǎng)術(shù)語的設(shè)計(jì)和維護(hù)的考慮。 第一,對(duì)你的接口實(shí)現(xiàn)進(jìn)行硬編碼;第二,如果你需要在別的JSP中用到同一個(gè)接口實(shí)現(xiàn),你需要拷貝你全路徑。解決這兩個(gè)問題的有效辦法就是在Preferences中聲明一切。

    1.1.?Preferences表

    下面列出的是可以在Preferences中申明的所有接口。Tag列展示的是eXtremeTable的標(biāo)簽,Attribute 列展示的是相關(guān)標(biāo)簽的對(duì)應(yīng)屬性。Interface列展示的是需要被實(shí)現(xiàn)的Java接口。Preference Key列展示的是 Preferences里對(duì)應(yīng)的健。

    Tag Attribute Interface Preference Key
    TableTag filterRowsCallback org.extremecomponents.table.callback.FilterRowsCallback table.filterRowsCallback
    TableTag intercept org.extremecomponents.table.intercept.InterceptTable table.intercept
    TableTag retrieveRowsCallback org.extremecomponents.table.callback.RetrieveRowsCallback table.retrieveRowsCallback
    TableTag sortRowsCallback org.extremecomponents.table.callback.SortRowsCallback table.sortRowsCallback
    TableTag state org.extremecomponents.table.state.State table.state
    TableTag view org.extremecomponents.table.view.View table.view
    RowTag intercept org.extremecomponents.table.intercept.InterceptRow row.intercept
    ColumnTag calc org.extremecomponents.table.calc.Calc column.calc
    ColumnTag cell org.extremecomponents.table.cell.Cell column.cell
    ColumnTag filterCell org.extremecomponents.table.cell.Cell column.filterCell
    ColumnTag headerCell org.extremecomponents.table.cell.Cell column.headerCell
    ColumnTag intercept org.extremecomponents.table.intercept.InterceptColumn column.intercept
    ExportTag intercept org.extremecomponents.table.intercept.InterceptExport export.intercept
    ExportTag view org.extremecomponents.table.view.View export.view
    ExportTag viewResolver org.extremecomponents.table.filter.ViewResolver export.viewResolver

    提示:當(dāng)在寫作本指南的時(shí)候,我意識(shí)到我忘記了讓標(biāo)簽ColumnsTag的autoGenerateColumns 屬性和Preferences協(xié)同工作。這將在下一版修正。

    1.2.?指定Preference別名

    上表展示了如何聲明preference鍵,但是沒有解釋如何指定有意義的別名。如果你注意到preference鍵提供了一致的語法 tag.attribute,指定鍵的別名僅僅是在它的基礎(chǔ)上進(jìn)行擴(kuò)展。它的語法為: tag.attribute.alias

    eXtremeTable提供了一個(gè)名為RowCountCell定制的cell,它的作用是現(xiàn)實(shí)當(dāng)前的行數(shù)。我將在Preferences里使用ColumnTag cell聲明來示范RowCountCell的使用。

    首先通過實(shí)現(xiàn)Cell接口或者擴(kuò)展AbstractCell來編寫具體的實(shí)現(xiàn)類。

    public class RowCountCell extends AbstractCell {
    protected String getCellValue(TableModel model, Column column) {
    int rowcount = ((model.getLimit().getPage() - 1)
    * model.getLimit().getCurrentRowsDisplayed())
    + model.getRowHandler().getRow().getRowCount();
    return String.valueOf(rowcount);
    }
    }

    然后在Preferences (屬性文件)進(jìn)行聲明并給出別名。eXtremeTable在一個(gè)Preferences里保存所有的配置信息,你可以通過使用本地 Preferences的來覆蓋任何的這些屬性。

    RowCountCell默認(rèn)的別名是rowCount:

    column.cell.rowCount=org.extremecomponents.table.cell.RowCountCell

    在ColumnTag中通過別名引用Cell:

    <ec:column alias="count" cell="rowCount"/>

    現(xiàn)在你可以通過rowCount來引用這個(gè)Cell,如果包名改變了你只需要對(duì)Preferences進(jìn)行修改。

    提示:本示例中我使用了ColumnTag的別名屬性。別名屬性應(yīng)用在有兩列使用同樣的property,也應(yīng)用在列不直接和列的 bean property關(guān)聯(lián)的情況下。本示例就屬于這種情況。



    Lyyb2001
    主站蜘蛛池模板: 国产亚洲av片在线观看16女人| 日韩精品免费一级视频| 污视频网站在线观看免费| 亚洲色成人网站WWW永久四虎| 亚洲AV无码久久久久网站蜜桃 | 免费国产黄网站在线观看| 182tv免费视频在线观看 | 亚洲字幕在线观看| 久久久久亚洲AV无码专区首JN| 亚洲天天做日日做天天欢毛片| 亚洲日韩v无码中文字幕| 久久亚洲国产精品123区| 久久亚洲中文字幕精品一区四| 国产国拍亚洲精品福利| 精品亚洲一区二区三区在线观看 | 18禁成年无码免费网站无遮挡| 成人免费福利电影| 嫩草视频在线免费观看| 好爽…又高潮了毛片免费看| 成人午夜视频免费| 国产免费拔擦拔擦8x| 免费国产综合视频在线看| 亚洲黄黄黄网站在线观看| 亚洲中文字幕伊人久久无码| 亚洲乱码国产一区三区| 久久久久亚洲av无码专区导航| 亚洲无线一二三四区| 亚洲中文精品久久久久久不卡| 亚洲欧美日韩久久精品| 极品美女一级毛片免费| 中文字幕av无码不卡免费| 99国产精品免费视频观看| 中文字幕无码不卡免费视频| 日韩高清在线免费观看| 亚洲乱码日产精品a级毛片久久| 久久精品国产亚洲麻豆| 亚洲成人黄色网址| 色九月亚洲综合网| 在线免费观看h片| 久久久高清免费视频| 免费人成在线观看网站视频|