解决方案

eXtremeComponents指南

seo靠我 2023-09-24 10:13:25
extremeComponents指南

eXtremeComponents指南

eXtremeComponents指南

Jeff Johnston

版本1.0.0

本文档允许在遵守以下两条原则的条件下被使用和传SEO靠我播: 1)不能凭借本文档索取任何费用 2)以任何方式(印刷物或电子版)使用和传播时本文档时,必须包含本版权申明

(更新中...)

Table of Contents

定制FilterCell 1. 引言 1SEO靠我.1. 定制Droplist过滤器Cell示例 定制FilterRowsCallback 1. 引言 1.1. 定制FilterRowsCallback示例 Form指南 1. 引言 1.1. JSPSEO靠我 1.1.1. Form特性的技术说明 1.1.2. Checkbox 1.1.3. Custom Cell 1.1.4. JavaScript 1.2. Cell 1.3. Controller 1SEO靠我.3.1. 表标签动作Controller 1.3.2. Form动作Controller 1.3.3. 重新得到Checkbox的值 Html视图定制指南 1. 引言 1.1. View接口 1.2SEO靠我. Messages示例 拦截器使用指南 1. 引言 1.1. 拦截器列表 1.2. 行拦截器示例 Limit指南 1. 引言 1.1. JSP 1.2. Controller 1.3. ServicSEO靠我e 1.3.1. 取得总行数 1.3.2. 取得Collection 1.4. DAO 1.4.1. 定义Query字符串 1.4.2. Filter 和 Sort Query 字符串 1.4.3. SEO靠我Limit Query String 1.4.4. 取回总行数和Collection. 1.4.5. 默认的Sort顺序 Preferences 指南 1. 引言 1.1. Preferences表 SEO靠我1.2. 指定Preference别名

定制FilterCell

1. 引言

列的filterCell属性控制过滤器如何显示,它和cell属性非常相像并且也是实现Cell接口。马上要定义的是默认的和dropSEO靠我list这两个过滤器cells。 默认的是一个输入框元素而droplist是一个下拉列表元素。当然,如果你需要进行一些定制你可以插接自己的实现。

最近,我被问到是否能够实现一个过滤器cell,显示已经通SEO靠我过别的过滤器过滤得到数据子集。答案当然是肯定的,而且这是我将在这里示范的。通常定制的 cell可以很容易被创建,这个示例将印证这点。在这个示例里last name列里显示的将是通过first nameSEO靠我过滤后的子集。如果没有通过 first name过滤那么所有值都将被显示。

1.1. 定制Droplist过滤器Cell示例

通常你只需要为过滤器cell实现Cell接口。然而,因为我们要创建的过滤器ceSEO靠我ll是一个下拉列表,我们可以通过扩展 FilterDroplistCell来获得它已经提供的很多功能,FilterDroplistCell是发行包已经提供的cells之一。

我们需要覆盖FilterDrSEO靠我oplistCell的唯一方法是getFilterDropList()。这是整个类的全部代码:

public class FilteredDroplistCell extends FilterDroplSEO靠我istCell {

private static Log logger = LogFactory.getLog(FilterDroplistCell.class);

protected List getFSEO靠我ilterDropList(TableModel model, Column column) {

List droplist = new ArrayList();

String firstNameFiltSEO靠我er = model.getLimit().getFilterSet().getValue("firstName");

Collection beans = model.getCollectionOfBSEO靠我eans();

for (Iterator iter = beans.iterator(); iter.hasNext();) {

Object bean = iter.next();

try {

StrinSEO靠我g firstName = BeanUtils.getProperty(bean, "firstName");

if (StringUtils.isNotBlank(firstNameFilter) &SEO靠我& !firstName.equals(firstNameFilter)) {

continue;

}

String lastName = BeanUtils.getProperty(bean, columSEO靠我n.getProperty());

if ((lastName != null) && !droplist.contains(lastName)) {

droplist.add(lastName);

}

} SEO靠我catch (Exception e) {

logger.debug("Problems getting the droplist.", e);

}

}

Collections.sort(droplist);SEO靠我

return droplist;

}

}

如果你比较这个类和父类,你会发现它们只有微小的区别。

首先需要注意的是我们需要找出first name是否已经被过滤了。

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

然后我们需要判断当前bean的first name值是否和first name过滤器值相SEO靠我同。如果相同,将当前的last name值 添加到droplist中。

String firstName = BeanUtils.getProperty(bean, "firstName");

if (SSEO靠我tringUtils.isNotBlank(firstNameFilter) && !firstName.equals(firstNameFilter)) {

continue;

}

如果last nameSEO靠我将添加到droplist中,我们需要检查droplist中是否已经包含了这个值。如果没有,我们就把它添加到droplist中。

String lastName = BeanUtils.getProperSEO靠我ty(bean, column.getProperty());

if ((lastName != null) && !droplist.contains(lastName)) {

droplist.addSEO靠我(lastName);

}

为了使用这个Cell你应该在Preferences中声明一个别名。 当然,你可以省略这步而在JSP中提供这个Cell实现类的全路径,但是使用Preferences更简洁。

colSEO靠我umn.filterCell.filteredDroplist=org.extremesite.cell.FilteredDroplistCell

在ColumnTag通过设置filterCell属性来SEO靠我使用FilteredDroplistCell。

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

如果不清楚PreferenceSEO靠我s和ColumnTag定义语法请参考Preferences指南。

定制FilterRowsCallback

1. 引言

FilterRowsCallback被用来过滤传给eXtremeTable的BeansSEO靠我的Collection。 FilterRowsCallback的默认实现是得到Beans或Maps的Collection,然后通过实现jakarta Predicate接口来进行过滤。当然,如果你需要SEO靠我进行一些定制你可以插接自己的实现。

首先声明,本示例代码包含一些从原包中剪切、粘贴的代码(虽然不是很多)。在 最初的最终发行包之后,值过滤得到进一步改善使得更具复用性并更容易实现,可能和定制cell代码SEO靠我行数相同。 当然,我被要求并非常乐意示范如何在当前代码基础上实现定制过滤。这有非常清晰的hooks实现,并且很容易实现。

本示例示范了如何调整代码为过滤器提供一个精确的比较功能。当前的实现是通过使用StSEO靠我ringUtils.contains()方法进行模糊比较。 本示例将使用StringUtils.equals()方法。你可以按照你的需要来调整代码进行更多定制。

1.1. 定制FilterRowsCalSEO靠我lback示例

首先你需要做的是创建一个实现Predicate接口的定制类。Predicate要求我们实现evaluate()方法来判断是否包含 当前bean。因为你仅仅调整现在已有的功能,首先得到fiSEO靠我lterPredicate的源代码(在发行包的callback包下), 拷贝到你的工程里。然后向下面展示的一样将 StringUtils.contains()方法修改为StringUtils.equaSEO靠我ls()方法:

public final class ExactMatchFilterPredicate implements Predicate {

private boolean isSearchMaSEO靠我tch(String value, String search) {

...

else if (StringUtils.equals(value, search)) {

return true;

}

...

}

}SEO靠我

然后我们需要实现和Predicate共同作用的FilterRowsCallback接口。再一次从发行包的callback包下拷贝ProcessRowsCallback源代码到你的工程里。 请参照我们创SEO靠我建的定制的ExactMatchFilterPredicate 类来确认仅仅实现了FilterRowsCallback和修改Predicate。

public class ExactMatchFilterSEO靠我Rows implements FilterRowsCallback {

public Collection filterRows(TableModel model, Collection rows) SEO靠我throws Exception {

...

if (filtered) {

Collection collection = new ArrayList();

Predicate filterPredicatSEO靠我e = new ExactMatchFilterPredicate(model);

CollectionUtils.select(rows, filterPredicate, collection);

rSEO靠我eturn collection;

}

...

}

}

为了使用这个FilterRowsCallback你应该在Preferences中声明一个别名。当然,你可以省略这步而在JSP中提供这个FilterRowsSEO靠我Callback实现类的全路径,但是使用Preferences更简洁。

table.filterRowsCallback.exactMatch=org.extremesite.callback.ExacSEO靠我tMatchFilterRows

在TableTag通过设置filterRowsCallback属性来使用ExactMatchFilterRows。

<ec:table filterRowsCallbacSEO靠我k="exactMatch"/>

如果不清楚Preferences和ColumnTag定义语法请参考Preferences指南。

Form指南

1. 引言

eXtremeTable本质上是一个form组件,所SEO靠我以我假定表被包在form里,所有的功能都被认为是对form元素的操作。如果你想在表体中包含一些定制的form元素, 或者想将eXtremeTable嵌入到另外的form中,那么你就要使用表标签的forSEO靠我m属性用来参照最近的form。

为了示范form特性,我们要做的工作将分解为JSP,Cell和Controller。

1.1. JSP

下面列出的是checkbox示例的完整代码。想要强调的主要事情是表标签SEO靠我form属性设置为presForm,它参照被称为presForm的form元素。

同时请注意表标签的autoIncludeParameters属性。进行排序、过滤、分页时,默认的eXtremeTableSEO靠我将保持所有传至JSP页面的参数。 这个特性对于内部其他的form进行排序、过滤、分页时,用于高效复制form元素同样有效。可以设置 autoIncludeParameters属性为false来固定它。SEO靠我

在这个form使用id属性是因为xhtm标准的要求,同时你也可以使用form的name属性。

Enter your name:

type="text"

name="userNSEO靠我ame"

style="font-family:verdana,arial,helvetica,sans-serif;font-size:11px;"

value=""

/>

items="presidentSEO靠我s"

action="${pageContext.request.contextPath}/selectedPresidentsController.run"

view="compact"

imagePatSEO靠我h="${pageContext.request.contextPath}/images/table/compact/*.gif"

rowsDisplayed="8"

autoIncludeParametSEO靠我ers="false"

form="presForm"

>

fileName="output.pdf"

tooltip="Export PDF"

headerColor="black"

headerBackgroSEO靠我undColor="#b6c2da"

headerTitle="Presidents"

/>

alias="checkbox"

title=" "

width="5px"

filterable="false"

soSEO靠我rtable="false"

viewsAllowed="compact"

cell="selectedPresident"

/>

type="button"

name="sel"

class="button"

vSEO靠我alue="List Selected Presidents"

οnclick="document.forms.presForm.submit();"

/>

function setPresideSEO靠我ntState(chkbx) {

//make sure that always know the state of the checkbox

if (chkbx.checked) {

eval(documSEO靠我ent.forms.presForm.chkbx_ + chkbx.name).value=SELECTED;

} else {

eval(document.forms.presForm.chkbx_ +SEO靠我 chkbx.name).value=UNSELECTED;

}

}

</form> 1.1.1. Form特性的技术说明

表标签form属性参照最近的form是你使用这个特性所必须知道的,为了更好的理解这个SEO靠我特性,介绍更多的关于内部实现技术的细节是值得的。

如果您不特意指定form属性,eXtremeTable自动在表附近包上一个form。所有表的动作例如:排序、过滤、分页将自动给一些隐藏的input元素赋SEO靠我值,然后提交这个form到表标签action属性设置的Aciton。 这非常有效,除非您想要将自己的form元素设置到表体,或者想将这个表放到别的form里。

表标签form属性参照最近的form,所有SEO靠我表的动作例如:排序、过滤、分页将自动给一些隐藏的input元素赋值,但是现在 最近form的action属性将要改变表标签的动作。这非常重要,因为:当排序、过滤、分页时,eXtremeTable能够从SEO靠我一个controller得到数据集合 ,但是提交这个form到别的controller来处理这个form时需要对用户的输入进行处理。然而,这些对于你使用表标签来说都是透明的。 就像你现在做的那样简单地SEO靠我设置表标签的action属性,然后设置相关的form到你想提交的位置。

1.1.2. Checkbox

示例的第一列是checkbox。因为这列不需要参照bean的属性,alias属性用来唯一地标识这列。SEO靠我你可以使用property 属性,但是alias属性使这列如何使用更清楚。alias属性还被用来当同样的属性被多列使用时唯一地标识一列。

1.1.3. Custom Cell

您也许想知道定制的cell是SEO靠我如何通过名称selectedPresident被参照的(cell="selectedPresident")。这是一个 对eXtremeTable的preferences特性更强的使用。所有要做的就是在SEO靠我extremecomponents.properties文件中添加一个属性。 请参考Preferences来了解更多的信息

column.cell.selectedPresident=org.extreSEO靠我mesite.cell.SelectedPresidentCell

column.cell.selectedPresident就是你定义的用来参照这个cell的名称。

当然你也可以使用这个Cell的全名来SEO靠我进行参照。

alias="checkbox"

title=" "

width="5px"

filterable="false"

sortable="false"

viewsAllowed="compact"

celSEO靠我l="org.extremesite.cell.SelectedPresidentCell"

/>

在属性文件中定义参照更方便,它可以被任何JSP文件引用。如果类名或包名改变的话你只需要对一个地方进行修改SEO靠我

1.1.4. JavaScript

JavaScript的setPresidentState()方法被定制cell用来设置每个checkbox元素的是否被选中。 设置一个隐藏元素的原因是为了获得浏览器SEO靠我的动作而不提交没有选中的checkbox。通过这个Controller将一直知道一个元素是否别选中。

1.2. Cell

定制的cell被用来生成checkbox,另外它也创建一个隐藏元素用来表示这个chSEO靠我eckbox元素是否被选中。 当用户进行排序、过滤、分页时,被选中的数据集合将被放到session里。

getExportDisplay()方法没有返回值,因为治理只需要Html显示。

public clSEO靠我ass SelectedPresidentCell implements Cell {

public String getExportDisplay(TableModel model, Column cSEO靠我olumn) {

return null;

}

public String getHtmlDisplay(TableModel model, Column column) {

HtmlBuilder htmlSEO靠我 = new HtmlBuilder();

CellBuilder.tdStart(html, column);

try {

Object bean = model.getCurrentRowBean();SEO靠我

String presidentId = BeanUtils.getProperty(bean, "presidentId");

Collection selectedPresidentsIds = (SEO靠我Collection)model.getContext().getSessionAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS);

iSEO靠我f (selectedPresidentsIds != null && selectedPresidentsIds.contains(presidentId)) {

html.input("hiddenSEO靠我").name("chkbx_" + presidentId).value(SelectedPresidentsConstants.SELECTED).xclose();

html.input("cheSEO靠我ckbox").name(BeanUtils.getProperty(bean, "presidentId"));

html.onclick("setPresidentState(this)");

htmSEO靠我l.checked();

html.xclose();

} else {

html.input("hidden").name("chkbx_" + presidentId).value(SelectedPrSEO靠我esidentsConstants.UNSELECTED).xclose();

html.input("checkbox").name(BeanUtils.getProperty(bean, "presSEO靠我identId"));

html.onclick("setPresidentState(this)");

html.xclose();

}

} catch (Exception e) {}

CellBuildeSEO靠我r.tdEnd(html);

return html.toString();

}

}

1.3. Controller

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

当在另SEO靠我外的form中使用eXtremeTable时,你可能有1个或2个controllers。当form被提交时,你需要一个controller 来处理用户的输入并重新定向到另外的JSP页面。当排序、过滤、SEO靠我分页时,你可能有另外的controller来得到表使用的数据集合并重定向会本页。或者你可以在同一个controller中分别处理。

checkbox示例里我使用一个controller来关联表标签的acSEO靠我tion属性。我也使用另外一个controller来关联form元素的动作。

1.3.1. 表标签动作Controller

这个controller负责调用SelectedPresidentsUtils来SEO靠我保存被选中的presidentIds到session里并回到同一页。

SelectedPresidentsUtils.saveSelectedPresidentsIDs(request);

CollectSEO靠我ion presidents = presidentsService.getPresidents();

request.setAttribute("presidents", presidents); 1SEO靠我.3.2. Form动作Controller

这个controller负责通过presidentIds得到数据集并重定向到下一个Jsp页面

Collection selectedPresidentsIdsSEO靠我 = SelectedPresidentsUtils.saveSelectedPresidentsIDs(request);

Collection selectedPresidents = SelectSEO靠我edPresidentsUtils.getSelectedPresidents(presidentsService.getPresidents(), selectedPresidentsIds);

reSEO靠我quest.setAttribute("selected", selectedPresidents);

request.getSession().removeAttribute(SelectedPresSEO靠我identsConstants.SELECTED_PRESIDENTS); 1.3.3. 重新得到Checkbox的值

我将列出保存presidentIds到session的代码。我经常被问到如何重新得SEO靠我到eXtremeTable中form元素的值。 它的原理是设置form输入元素名字属性值前面加上一些东西来唯一标识元素

本示例中我关心的是以chkbx开头参数的元素。chkbx后面是唯一的关联到checSEO靠我kbox的presidentId。它被用来判断这个checkbox是否别选中。

public static Collection saveSelectedPresidentsIDs(HttpServleSEO靠我tRequest request) {

Collection presidents = (Collection) request.getSession().getAttribute(SelectedPrSEO靠我esidentsConstants.SELECTED_PRESIDENTS);

if (presidents == null) {

presidents = new ArrayList();

requestSEO靠我.getSession().setAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS, presidents);

}

EnumerationSEO靠我 parameterNames = request.getParameterNames();

while (parameterNames.hasMoreElements()) {

String paramSEO靠我eterName = (String) parameterNames.nextElement();

if (parameterName.startsWith("chkbx_")) {

String preSEO靠我sidentId = StringUtils.substringAfter(parameterName, "chkbx_");

String parameterValue = request.getPaSEO靠我rameter(parameterName);

if (parameterValue.equals(SelectedPresidentsConstants.SELECTED)) {

if (!presidSEO靠我ents.contains(presidentId)) {

presidents.add(presidentId);

}

} else {

presidents.remove(presidentId);

}

}

}SEO靠我

return presidents;

}

Html视图定制指南

1. 引言

eXtremeTable使用View接口来生成HTML。你可以使用发行包已经提供的视图,或者你可以插入自己的视图实现。 现在,创建你SEO靠我自己的视图相对比较简单,但讨论一些设计想法和如何着手实现一个定制的视图还是有价值的。

我想使创建定制视图简单,但不是想构造一个更复杂的类似swing的模型,原因是那需要创建大量的对象来处理对应的内部工作SEO靠我。 eXtremeTable以高效为目标,我也想在视图的实现上贯彻这种想法,所以我决定创建一系列的静态构造器类来实现分解的最小功能。你可以通过组合这些功能来实现你的定制视图。

学习定制视图的最好途径是阅SEO靠我读已经存在的视图的源代码,修改它来满足你的需求。如果我示范所有东西的话,这篇指南将变的非常冗长。取而代之的是我将直接修改默认视图的工具条作为定制视图的一个示例。 对于不同构造器的具体细节我建议你阅读源SEO靠我代码。我也将尽量更新javadocs来提供更好的帮助。

1.1. View接口

实现View接口的类有3次插入内容的机会。beforeBody()方法会被立刻调用,body()方法在每一行的每一列处理的时SEO靠我候调用。 afterBody()方法是被eXtremeTable调用的最后方法,它将返回代表视图的一个对象。在这个HTML视图示例里,它将是一个字符串。

public interface View {

pSEO靠我ublic void beforeBody(TableModel model);

public void body(TableModel model, Column column);

public ObjSEO靠我ect afterBody(TableModel model);

}

1.2. Messages示例

在这篇指南里我将直接修改工具条来实现这网站上Messages示例的定制视图。

public class MSEO靠我essagesView extends AbstractHtmlView {

protected void toolbar(TableModel model) {

TwoColumnTableLayoutSEO靠我 toolbar = new MessagesToolbar();

toolbar.layout(getHtmlBuilder(), model);

}

protected void statusBar(TSEO靠我ableModel model) {

TwoColumnRowLayout statusBar = new MessagesStatusBar();

statusBar.layout(getHtmlBuiSEO靠我lder(), model);

}

}

这里使用的是默认视图,因此它扩展了虚拟视图来修改工具条和状态条。如何修改工具条和(或)状态条也是开发人员问的最多问题。

默认视图的工具条位于表的上方包括翻页链接和标题。SEO靠我工具条使用TwoColumnTableLayout,它是一个用于提供在自己表中实现左右两列布局的虚拟类。 它将实现能够浮在表上方的完美布局。下面就是你需要关心的虚拟方法,在实际的html视图中已经为你SEO靠我完成了这个布局。

public abstract class TwoColumnTableLayout {

protected abstract boolean showLayout(TableModelSEO靠我 model);

protected abstract void columnLeft(HtmlBuilder html, TableModel model);

protected abstract voSEO靠我id columnRight(HtmlBuilder html, TableModel model);

}

showLayout()方法用来阻止或导致布局的展现。在我的定制视图中如果翻页或(和)导出显示那SEO靠我么工具条将展现。

protected boolean showLayout(TableModel model) {

boolean showPagination = BuilderUtils.showPaSEO靠我gination(model);

boolean showExports = BuilderUtils.showExports(model);

if (!showPagination && !showExSEO靠我ports) {

return false;

}

return true;

}

下面显示了左列和右列的部分代码。注意在我的定制视图中首页和前一页使用了文字来替代图片显示。我真正希望示范的是你需要做的:找到正确的SEO靠我构造器类并且仅仅是扩展HtmlBuilder的标签。 构造器类对于示范如何找到模型里的信息(以便你能够做比他们能够提供的更多的定制工作)也非常有用,。

protected void columnLeftSEO靠我(HtmlBuilder html, TableModel model) {

html.td(2).close();

TableBuilder.title(html, model);

html.tdEnd(SEO靠我);

}

protected void columnRight(HtmlBuilder html, TableModel model) {

boolean showPagination = BuilderUSEO靠我tils.showPagination(model);

...

if (showPagination) {

html.td(4).close();

ToolbarBuilder.firstPageItemAsSEO靠我Text(html, model);

html.tdEnd();

html.td(4).close();

ToolbarBuilder.prevPageItemAsText(html, model);

htmSEO靠我l.tdEnd();

...

}

...

}

为了使用这个视图你需要在Preferences定义一个别名。 你可以省略这部而在JSP直接给出这个视图的完整有效的类名,不过Preferences更为简洁。

tablSEO靠我e.view.messages=org.extremesite.view.MessagesView

TableTag也将设置视图属性来使用MessagesView视图。

<ec:table view="mSEO靠我essages">

如果不清楚Preferences和TableTag定义语法请参考Preferences指南。

拦截器使用指南

1. 引言

拦截特性被用在运行时需要修改属性值的时候,它使得改变基于数据的eXSEO靠我tremeTable的行为成为可能。在阅读扩展标签属性时,你会发现它和扩展标签属性具有同样的概念和方法标识。 区分使用他们的首要准则是:如果需要向TLD里已经定义的并且能够在JSP中访问的标签添加新的SEO靠我属性时,应该使用扩展标签属性;如果仅仅是需要修改已经定义好的属性的值的时候,应该使用拦截器。

你可能需要了解更多的eXtremeTable如何运作的技术背景才能完全理解这种特性。 eXtremeTablSEO靠我e首先做的就是遍历所有标签并创建对应的模型beans (pojos)。beans是具有和标签一样属性,但是使用真实类型来替换仅仅使用字符串类型的对象。beans是被模型使用并且是你需要使用拦截特性修改SEO靠我的对象。 所有的拦截器接口都定义了一个add方法, add方法被用来处理模型bean第一次创建时的属性。行和列的拦截器还有一个modify 方法。modify方法可以在当行和类进行处理是对属性值进行操SEO靠我作。

1.1. 拦截器列表

下面列出了具有拦截特性的标签和他们需要被实现的接口,Bean栏显示了被模型创建的Bean。

标签接口BeanTableTagorg.extremecomponents.tableSEO靠我.intercept.InterceptTableorg.extremecomponents.table.bean.TableRowTagorg.extremecomponents.table.intSEO靠我ercept.InterceptRoworg.extremecomponents.table.bean.RowColumnTagorg.extremecomponents.table.intercepSEO靠我t.InterceptColumnorg.extremecomponents.table.bean.ColumnExportTagorg.extremecomponents.table.interceSEO靠我pt.InterceptExportorg.extremecomponents.table.bean.Export

1.2. 行拦截器示例

示范拦截特性的完美示例就是根据一定的标准来对行进行高亮显示,这也SEO靠我是我们将要完成的示例。它很短也很简单,不过它实现的概念同样适用于每一个拦截器接口。

我们需要做的第一件事就是实现InterceptRow接口。你会注意到这个接口有两个方法:addRowAttributeSEO靠我s() 和modifyRowAttributes()。addRowAttributes方法在行bean创建的时候被调用, modifyRowAttributes方法在表处理当前页面行的时候被调用。

puSEO靠我blic class MarkerIntercept implements InterceptRow {

public void addRowAttributes(TableModel tableModSEO靠我el, Row row) {

}

public void modifyRowAttributes(TableModel model, Row row) {

President president = (PrSEO靠我esident) model.getCurrentRowBean();

String career = president.getCareer();

if (StringUtils.contains(caSEO靠我reer, "Soldier")) {

row.setStyle("background-color:#fdffc0;");

} else {

row.setStyle("");

}

}

}

在PreferenceSEO靠我s里你应该定义这个行拦截器的别名。

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

这样就可以在行标签中使用拦截器MarkerSEO靠我Intercept了。

<ec:row intercept="marker">

如果不清楚Preferences和TableTag定义语法请参考Preferences指南。

Limit指南

1. 引言

在你需要SEO靠我处理大量数据时你应该考虑使用eXtremeTable的Limit特性。Limit这个名字来自MySQL的limit 命令,Limit接口的目的就是如何对表的结果集进行limit处理。Limit实现知道SEO靠我当排序、过滤、分页、导出时,用户如何与表互相作用。有了这些信息你 将能够使用可能是最有效的方式显示正确的过滤、排序后的请求页面。

为了示范Limit特性,我将要做的工作将分解为JSP、ControlleSEO靠我r、Service和DAO。这示范了一种使用分层的方式来处理 Limit。你可以根据自己的需要来增加或减少层。本示例也使用了Spring框架来重新得到使用Spring的JDBC取得的数据,因此你的代码SEO靠我看起来可能有点不同。eXtremeTable的一个特点就是不依赖任何框架和容器。

1.1. JSP

为了使用Limit特性,eXtremeTable需要使用limit特定的RetrieveRowsCallSEO靠我back、 FilterRowsCallback和SortRowsCallback接口。eXtremeComponents提供了每个接口的一个实现,可以简单地通过设置每个属性值为limit来简单来使用SEO靠我

items="presidents"

retrieveRowsCallback="limit"

filterRowsCallback="limit"

sortRowsCallback="limit"

vieSEO靠我w="limit"

>

...

另外视图属性参照一个名为limit的定制视图。这是一个简单修改默认eXtremeTable视图,不包含最后页工具条的实现。这仅仅关系到你是否能取得确切需要的行。 一些数据库例SEO靠我如Oracle和MySQL都提供了一种得到确定行的特性,但是,其他的数据库例如:Sybase没有提供特性。在我的示例中我考虑最坏的情况你的数据库不支持这种特性。

即使你的数据库不提供取得特定行的特性,当SEO靠我你考虑用户如何和表协同工作时,Limit仍然非常有意义。用户通常会对一些数据进行排序、过滤和分页。 这个例子中15条数据构成一页,第一页需要15条数据,第二页需要30条数据,第三页需要45条数据,以此SEO靠我类推。在经过一段时间分页后,他们常常使用过滤来提炼数据。 即使他们不这样做,他们也必须在此之前对大量的数据进行分页,这将影响效率。当然如果允许用户点击最后页,那么所有的数据都将被取出,这将非常影响效率SEO靠我

1.2. Controller

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

controller首先需要创建一个Limit。为了完成这个你需要得到一些关于CoSEO靠我ntext和LimitFactory的帮助。

Context context = new HttpServletRequestContext(request);

LimitFactory limitFacSEO靠我tory = new TableLimitFactory(context);

Limit limit = new TableLimit(limitFactory);

Context是一个处理取得属性的接口SEO靠我,LimitFactory使用Context来找出用户如何和eXtremeTable交互。 然后Limit使用LimitFactory来组装自己。

为了初始化Limit,它将包含所有的有用的信息。这些信SEO靠我息包括数据将被如何排序和过滤,哪一页将被显示和是否允许被导出。

然而,Limit仍然需要得到行的信息,这样正确的信息页面才能被显示给用户。行信息包括开始行、结束行、当前显示行。 controller必须SEO靠我从service得到这些信息,而Service将从dao中得到这些信息。这里我只给出Controller端的代码。

int totalRows = presidentsService.getTotalPSEO靠我residents(limit.getFilterSet(), limit.isExported());

limit.setRowAttributes(totalRows, defaultRowsDisSEO靠我played);

limit需要得到所有的行来得到行的信息。service需要知道那些被过滤,不管这些数据是否要导出。为了设置行信息,默认的一页显示的行数需要被设置。 这可以通过对TableTag的roSEO靠我wsDisplayed属性设置一个确定的数值来实现。

现在我们只需要从services得到Collection数据。

Collection presidents = presidentsService.gSEO靠我etPresidents(limit.getFilterSet(), limit.getSort(), limit.getRowEnd());

因为limit已经包含所有信息,这将十分容易。所有需要做的SEO靠我就是传入过滤器,排序和最后行的信息。 最后要做的是将Collections和totalRow这些信息传送回JSP以便eXtremeTable知道如何显示这些信息。

request.setAttributSEO靠我e("presidents", presidents);

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

1.3. Service

seSEO靠我rvice需要和dao进行交互来得到总行数和Collection。

1.3.1. 取得总行数

controller需要到第一条信息就是总行数。

public int getTotalPresidents(FSEO靠我ilterSet filterSet, boolean isExported) {

String totalQuery = presidentsDao.getTotalPresidentsQuery()SEO靠我;

String modTotalQuery = filterQuery(filterSet, totalQuery);

int totalRows = presidentsDao.getTotalPreSEO靠我sidents(modTotalQuery);

if (isExported && totalRows > maxExportRows) {

totalRows = maxExportRows;

}

retuSEO靠我rn totalRows;

}

service和dao一起来过滤结果集,它的工作方式是在Where语句后面增加更多的AND语句来修改查询字符串。为此,你需要和Limit FilterSet一起工作。

FilSEO靠我terSet是一个过滤器对象数组,一个过滤器包括一个bean property和这个过滤器的值。或者,简单的说就是用户想要过滤的行和他们输入的值。这使得它非常容易交互。service只需要迭代所有的 SEO靠我FilterSet并调用dao来拼接查询语句。(译者注:过滤的实现方式是:在Where后面增加And语句来改变查询语句以达到对数据进行过滤的效果)

private String filterQuery(SEO靠我FilterSet filterSet, String query) {

if (!filterSet.isFiltered() || filterSet.isCleared()) {

return quSEO靠我ery;

}

Filter filters[] = filterSet.getFilters();

for (int i = 0; i < filters.length; i++) {

Filter filtSEO靠我er = filters[i];

String property = filter.getProperty();

String value = filter.getValue();

query = presSEO靠我identsDao.filterQuery(query, property, value);

}

return query;

}

query修改包括了filter信息,总行数。在一些情况下这就足够,但是当用户SEO靠我导出数据时仍然存在一个潜在的问题。为了保持高效 service不允许导出超出一个最大行数的数据。

1.3.2. 取得Collection

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

puSEO靠我blic Collection getPresidents(FilterSet filterSet, Sort sort, int rowEnd) {

String patientsQuery = prSEO靠我esidentsDao.getPresidentsQuery();

String modPatientsQuery = filterQuery(filterSet, patientsQuery);

modSEO靠我PatientsQuery = sortQuery(sort, modPatientsQuery);

modPatientsQuery = presidentsDao.limitQuery(rowEndSEO靠我, modPatientsQuery);

return presidentsDao.getPresidents(modPatientsQuery);

}

和前面一样,service和dao一起来过滤结果集。SEO靠我

另外query字符串需要扩展ORDER BY语句以便数据按照正确的方式进行排序。Sort包含一个bean property和 sortOrder值(正序还是逆序)。service仅仅需要使用Sort来SEO靠我调用dao。

private String sortQuery(Sort sort, String query) {

if (!sort.isSorted()) {

String defaultSortOrSEO靠我der = presidentsDao.getDefaultSortOrder();

if (StringUtils.isNotBlank(defaultSortOrder)) {

return querSEO靠我y + defaultSortOrder;

}

return query;

}

String property = sort.getProperty();

String sortOrder = sort.getSEO靠我SortOrder();

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

}

query字符串最后需要的修改就是增加数据库特别的指令来SEO靠我limit将要被返回的结果集。这就是limitQuery() 方法的作用。

1.4. DAO

dao为service负责底层数据工作。

1.4.1. 定义Query字符串

为了真正理解dao,query字符串SEO靠我需要被展示。

这就是得到数据的presidents query字符串:

private final static String presidentsQuery =

" SELECT " +

" presideSEO靠我nt_id presidentId, " +

" first_name firstName, " +

" last_name lastName, " +

" nick_name nickName, " +

"SEO靠我 concat(first_name, ,last_name) fullName, " +

" term, " +

" born, " +

" died, " +

" education, " +

" careSEO靠我er, " +

" political_party politicalParty " +

" FROM presidents ";

这是得到总行数的query字符串:

private final staticSEO靠我 String totalPresidentsQuery =

" SELECT count(*) FROM presidents "; 1.4.2. Filter 和 Sort Query 字符串

两个最SEO靠我有趣的方法就是过滤和排序。

filter看起来像这样:

public String filterQuery(String query, String property, String value) {

StSEO靠我ringBuffer result = new StringBuffer(query);

if (query.indexOf("WHERE") == -1) {

result.append(" WHERESEO靠我 1 = 1 "); //stub WHERE clause so can just append AND clause

}

if (property.equals("fullName")) {

resulSEO靠我t.append(" AND concat(first_name, ,last_name) like %" + value + "%");

} else if (property.equals("nicSEO靠我kName")) {

result.append(" AND nick_name like %" + value + "%");

} else {

result.append(" AND " + propeSEO靠我rty + " like %" + value + "%");

}

return result.toString();

}

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

sort看SEO靠我起来非常类似:

public String sortQuery(String query, String property, String sortOrder) {

StringBuffer resultSEO靠我 = new StringBuffer(query + " ORDER BY ");

if (property.equals("fullName")) {

result.append("concat(fiSEO靠我rst_name, ,last_name) " + sortOrder);

} else {

result.append(property + " " + sortOrder);

}

return resulSEO靠我t.toString();

}

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

1.4.3. Limit Query String

现在query字符串修改能够正确的进行fiSEO靠我lter和sort,它还需要修改以便只取页面显示相关的数据。MySQL为s the limit命令。

public String limitQuery(int rowEnd, String query)SEO靠我 {

return query + " limit " + rowEnd;

} 1.4.4. 取回总行数和Collection.

service需要的唯一东西就是:总行数和Collection。

publicSEO靠我 Collection getPresidents(final String query) {

return jdbcTemplate.query(query, new ResultReader() {SEO靠我

List results = new ArrayList();

public List getResults() {

return results;

}

public void processRow(ResuSEO靠我ltSet rs)

throws SQLException {

President president = new President();

president.setPresidentId(new IntSEO靠我eger(rs.getInt("presidentId")));

president.setFirstName(rs.getString("firstName"));

president.setLastNSEO靠我ame(rs.getString("lastName"));

president.setNickName(rs.getString("nickName"));

president.setFullName(SEO靠我rs.getString("fullName"));

president.setTerm(rs.getString("term"));

president.setBorn(rs.getDate("bornSEO靠我"));

president.setDied(rs.getDate("died"));

president.setEducation(rs.getString("education"));

presidenSEO靠我t.setCareer(rs.getString("career"));

president.setPoliticalParty(rs.getString("politicalParty"));

resuSEO靠我lts.add(president);

}

});

}

public int getTotalPresidents(final String query) {

return jdbcTemplate.querySEO靠我ForInt(query);

}

ResultReader是一个帮助处理JDBC查询的Spring特殊类,作为一个callback来处理JDBC ResultSet。jdbcTemplate是对JDBC连SEO靠我接的抽象。

1.4.5. 默认的Sort顺序

最后,这是service需要的默认sort顺序:

public String getDefaultSortOrder() {

return " ORDER BY SEO靠我concat(first_name, , last_name) ";

}

Preferences 指南

1. 引言

为了设置全局属性和设置,你需要使用Preferences特性,它现在使用一个属性文件来实现。SEO靠我本文档将很好地介绍如何在web.xml里设置Preferences, 以及一些需要被定义的通用属性。在这里我非常乐意介绍一些关于Preferences的进一步用法。

所有标签属性表示一个可插接的接口,它SEO靠我可以通过给出实现的全路径来设置。这为插接实现提供了一条便利的途径。当然这存在一些为过长术语的设计和维护的考虑。 第一,对你的接口实现进行硬编码;第二,如果你需要在别的JSP中用到同一个接口实现,你需要SEO靠我拷贝你全路径。解决这两个问题的有效办法就是在Preferences中声明一切。

1.1. Preferences表

下面列出的是可以在Preferences中申明的所有接口。Tag列展示的是eXtremeSEO靠我Table的标签,Attribute 列展示的是相关标签的对应属性。Interface列展示的是需要被实现的Java接口。Preference Key列展示的是 Preferences里对应的健。

TaSEO靠我gAttributeInterfacePreference KeyTableTagfilterRowsCallbackorg.extremecomponents.table.callback.FiltSEO靠我erRowsCallbacktable.filterRowsCallbackTableTaginterceptorg.extremecomponents.table.intercept.InterceSEO靠我ptTabletable.interceptTableTagretrieveRowsCallbackorg.extremecomponents.table.callback.RetrieveRowsCSEO靠我allbacktable.retrieveRowsCallbackTableTagsortRowsCallbackorg.extremecomponents.table.callback.SortRoSEO靠我wsCallbacktable.sortRowsCallbackTableTagstateorg.extremecomponents.table.state.Statetable.stateTableSEO靠我Tagvieworg.extremecomponents.table.view.Viewtable.viewRowTaginterceptorg.extremecomponents.table.intSEO靠我ercept.InterceptRowrow.interceptColumnTagcalcorg.extremecomponents.table.calc.Calccolumn.calcColumnTSEO靠我agcellorg.extremecomponents.table.cell.Cellcolumn.cellColumnTagfilterCellorg.extremecomponents.tableSEO靠我.cell.Cellcolumn.filterCellColumnTagheaderCellorg.extremecomponents.table.cell.Cellcolumn.headerCellSEO靠我ColumnTaginterceptorg.extremecomponents.table.intercept.InterceptColumncolumn.interceptExportTaginteSEO靠我rceptorg.extremecomponents.table.intercept.InterceptExportexport.interceptExportTagvieworg.extremecoSEO靠我mponents.table.view.Viewexport.viewExportTagviewResolverorg.extremecomponents.table.filter.ViewResolSEO靠我verexport.viewResolver

提示:当在写作本指南的时候,我意识到我忘记了让标签ColumnsTag的autoGenerateColumns 属性和Preferences协同工作。这将在SEO靠我下一版修正。

1.2. 指定Preference别名

上表展示了如何声明preference键,但是没有解释如何指定有意义的别名。如果你注意到preference键提供了一致的语法 tag.attribuSEO靠我te,指定键的别名仅仅是在它的基础上进行扩展。它的语法为: tag.attribute.alias。

eXtremeTable提供了一个名为RowCountCell定制的cell,它的作用是现实当前的行SEO靠我数。我将在Preferences里使用ColumnTag cell声明来示范RowCountCell的使用。

首先通过实现Cell接口或者扩展AbstractCell来编写具体的实现类。

public cSEO靠我lass RowCountCell extends AbstractCell {

protected String getCellValue(TableModel model, Column columSEO靠我n) {

int rowcount = ((model.getLimit().getPage() - 1)

* model.getLimit().getCurrentRowsDisplayed())

+ mSEO靠我odel.getRowHandler().getRow().getRowCount();

return String.valueOf(rowcount);

}

}

然后在Preferences (属性文件)进SEO靠我行声明并给出别名。eXtremeTable在一个Preferences里保存所有的配置信息,你可以通过使用本地 Preferences的来覆盖任何的这些属性。

RowCountCell默认的别名是rowSEO靠我Count:

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

在ColumnTag中通过别名引用Cell:

<ec:coSEO靠我lumn alias="count" cell="rowCount"/>

现在你可以通过rowCount来引用这个Cell,如果包名改变了你只需要对Preferences进行修改。

提示:本示例中我使用了SEO靠我ColumnTag的别名属性。别名属性应用在有两列使用同样的property,也应用在列不直接和列的 bean property关联的情况下。本示例就属于这种情况。

posted on 2006-02-SEO靠我26 10:00 Lucky 阅读(1047) 评论(14)   编辑  收藏 收藏至365Key 所属分类: extremeComponents

评论:

#  re: extremeComponentsSEO靠我指南 2006-03-04 10:33 | 一滴水

正好用上,谢谢:)   回复

   #  re: extremeComponents指南 2006-03-04 10:47 | Lucky

不客气,希望能为大家SEO靠我带来方便。现在我正在熟悉它的源代码,Jeff让我帮着添加一些小的特性(feature),希望大家有什么想法、建议...,请和我(xplucky@gmail.com)联系。   回复

#  提一个小bugSEO靠我 2006-04-13 15:18 | snowolf

翻页按钮提示是通过图片的title属性实现国际化的,但图片又定义了alt,使用的英文,当这个按钮没有链接的时候,title就没有定义,显示的提示就SEO靠我是alt的内容。   回复

   #  re: extremeComponents指南 2006-04-13 15:54 | xplucky

@snowolf

我自己测试了一下,并没有出现你说的那种情况啊?你用的SEO靠我extremeComponents的版本是多少?你能不能提供更详细一点的情况,或者抓副图mail给我。在线联系也行,我的MSN: zlh326@msn.com   回复

#  re: extremeCoSEO靠我mponents指南 2006-04-13 18:33 | snowolf

我用的是1.0.1M4,从sf上下的,我看你提到m5,我想要到cvs里去下吧

我碰到的bug,举个例子说,列表有多页,现在处在第SEO靠我一页,那么按钮第1页(First),前一页(Prev)这个时候是没有链接的,下一页(Next)、最后一页(Last)是有链接的,这时候我把鼠标放在这些按钮上时,会出现一个提示信息,

First、PrevSEO靠我是英文的,Next、Last是中文的。

生成的html代码是这样的

First

Prev

Next

Last

注意里面img里的title属性,当按钮有链接时,才会有这个属性

我刚到springside里看到这个用的是正常的,他用的是我下的这个版本SEO靠我的改造版(改造了excel输出的中文问题)

不知道是不是我配置的问题,郁闷   回复

   #  re: extremeComponents指南 2006-04-13 18:37 | snowolf

问题我想找到SEO靠我了,是资源文件的原因

我把springside里面改过的资源文件拿过来就行了

里面多了几行

toolbar.firstPageText=/u7b2c/u4e00/u9875

toolbar.lastPageTSEO靠我ext=/u6700/u540e/u9875

toolbar.nextPageText=/u4e0b/u4e00/u9875

toolbar.prevPageText=/u4e0a/u4e00/u9875SEO靠我

   回复

   #  re: extremeComponents指南 2006-04-13 18:40 | snowolf

原来**PageText才是定义alt的,没看源代码,推测出的问题出处有误,不好意思,麻烦SEO靠我你了   回复

   #  re: extremeComponents指南 2006-04-13 18:41 | xplucky

你还在线吗?M4版的中文资源文件比英文的少了一下东西。   回复

#  re: eSEO靠我xtremeComponents指南 2006-04-13 18:44 | xplucky

如果你愿意尝试,我可以给你最新的jar。有一些朋友已经再使用了,还没有收到太大问题的反馈。   回复

#  reSEO靠我: extremeComponents指南 2006-04-14 11:21 | snowolf

好啊,麻烦你发到我的邮箱snowolf9929(at)163.com 谢谢

我现在正在为新项目选一些组件和SEO靠我标签,刚开始看到displaytag,看到网上一些评论,发现eXtremeTable很不错,运行里面的test感受了一下,也尝试修改里面的一些属性,看到你翻译的文章,介绍里面有很多地方可以自己扩展,这SEO靠我种设计确实不错,还没尝试去做一个扩展的例子,感觉人还是挺懒,能不扩展就不扩展了,呵呵。

现在开源的东西很多,选用哪种也很令人头疼啊。。。   回复

#  re: extremeComponents指南 2SEO靠我006-04-14 11:41 | xplucky

@snowolf

我已经给你的163信箱发了,不过点的快了点,没加标题,不好意思。   回复

#  re: extremeComponents指南 200SEO靠我6-06-17 15:17 | sfd

extremeComponents的单元格能不能编辑!

   回复

   #  re: extremeComponents指南 2006-06-18 18:02 | Lucky

SEO靠我目前为止,还不具备编辑功能!   回复

   #  re: extremeComponents指南 2006-06-19 12:53 | sfd

能不能加上水平,垂直滚动条!   回复

 
“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2