说在前面的话:
ECSide组件,一个功能丰富,简单易用的列表组件,套用圈子里的一句话:它可能不是最好的,但也许是你最需要的。感兴趣的同志们可以访问ECSide的圈子,里面的资源及文档都很丰富,不在这里做过多的介绍了,圈子地址为
http://ecside.group.javaeye.com/
实例讲解:
实现从一张公告表读取公告信息并以列表展示的功能。本文中的源代码可通过这个链接下载。
开发环境:
Dev Tool: Eclipse 3.3
Web Server: Tomcat 5.5.23
Framework: Spring 2.0.6 + Hibernate 3.3.0 + Struts 1.2.8 + ecside_2.0_RC1
Database: Oracle 9i
实现步骤:
0) 准备工作
0) 准备工作
使用ecside工具,你需要准备的有:
1、ecside.jar
2、 ecside.tld标签
3、ecside.js
4、ecside.css
5、ecside使用table图片
注:以上内容均可在圈子中下载到。
1)配置ecside
需要在web.xml中配置ecside的过滤器,用于文件导出和语言编码,忘记配置的话,会出现“正在提交”的问题。
<!--
ecside export filter
-->
< filter >
< filter-name > ecsideExport </ filter-name >
< filter-class > org.ecside.filter.ECSideFilter </ filter-class >
< init-param >
< param-name > useEasyDataAccess </ param-name >
< param-value > true </ param-value >
</ init-param >
< init-param >
< param-name > useEncoding </ param-name >
< param-value > true </ param-value >
</ init-param >
< init-param >
< param-name > encoding </ param-name >
< param-value > UTF-8 </ param-value >
</ init-param >
</ filter >
< filter-mapping >
< filter-name > ecsideExport </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
< filter >
< filter-name > ecsideExport </ filter-name >
< filter-class > org.ecside.filter.ECSideFilter </ filter-class >
< init-param >
< param-name > useEasyDataAccess </ param-name >
< param-value > true </ param-value >
</ init-param >
< init-param >
< param-name > useEncoding </ param-name >
< param-value > true </ param-value >
</ init-param >
< init-param >
< param-name > encoding </ param-name >
< param-value > UTF-8 </ param-value >
</ init-param >
</ filter >
< filter-mapping >
< filter-name > ecsideExport </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
还需配置一下tld,
<
taglib
>
< taglib-uri > /WEB-INF/ecside.tld </ taglib-uri >
< taglib-location > /WEB-INF/taglib/ecside.tld </ taglib-location >
</ taglib >
< taglib-uri > /WEB-INF/ecside.tld </ taglib-uri >
< taglib-location > /WEB-INF/taglib/ecside.tld </ taglib-location >
</ taglib >
另外,还可以初始化ecside.properties文件,写这个文件的目的是:把公共的内容集中在一个文件中,方便使用。一旦我们使用ecside 组件,哪个这些配置信息就可以直接引用。形式可以如下:
########### table ###############
table.method=post
table.width=95%
table.pageSizeList=10,20,50,100,1000,2000,all
table.rowsDisplayed=10
table.sortable=true
########### column ###############
column.format.date=yyyy/MM/dd
column.format.number=0.##
column.format.currency=###,###,###
table.method=post
table.width=95%
table.pageSizeList=10,20,50,100,1000,2000,all
table.rowsDisplayed=10
table.sortable=true
########### column ###############
column.format.date=yyyy/MM/dd
column.format.number=0.##
column.format.currency=###,###,###
2) 在Struts Action中使用ecside
首先来简单介绍一下RSF(列表、排序、过滤)操作方式:
ecside支持两种RSF方式: 基于java collection层 和 基于数据库层,下面分别介绍:
ecside支持两种RSF方式: 基于java collection层 和 基于数据库层,下面分别介绍:
基于java collection层
这是ec的默认实现方式, 最简单易用.你要做的就是将整个列表所要展现的全部数据放入collection 内,并交给EC来处理.其中RSF操作,全部由EC在内存中完成,由于你已经将全部数据放入了collection中,所以排序 过滤都是基于全部数据的.你要在DAO中做的就是一个 查询操作,SQL语句中不需要加入 关于排序 分页 过滤的代码.
这种方式的优点非常明显:实现简单.缺点同样明显,而且在很大程度上是致命的: 数据量大的时候速度慢,而且很可能OutOfMemory.
基于数据库层
在这种方式下,EC的角色发生了一点点变化。此时,EC负责把 collection 里的内容展现出来, 同时会向你提供RSF相关的参数。而这些参数需要你自己手动取得 并传入到DAO中(当然EC提供了很多方便的方法来帮助你取得这些参数),具体功能的实现需要你自己在DAO中组织相应的SQL语句。
这种方式的优缺点正好和方式一相反。
我这里采用第二种基于数据库层的分页方式实现列表,这时在JSP中使用ecside时,要将<ec:table>中的几个重要属性设定为limit。如: <ec:table filterRowsCallback="process/limit" sortRowsCallback="process/limit" retrieveRowsCallback="process/limit" ...> 这里filterRowsCallback表示过滤的Callback方式,sortRowsCallback表示排序的Callback方式,retrieveRowsCallback表示分页的Callback方式,这三个属性都需要设定为limit。(不熟悉的读者可以查询原版EC中的相关说明,不在这里详述。)
Struts Action的代码为:
/**/
/*
* 用ECSide構建列表
*
*/
public ActionForward list(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String v_type = request.getParameter( " type " );
// 0) 設定過濾條件
Map < String, Object > filterMap = new HashMap < String, Object > ();
// filterMap.put("content", "test");
Map < String, Object > sortMap = new HashMap < String, Object > ();
sortMap.put( " createTime " , " desc " ); // 按照創建時間倒序排列
// 1) 設定ECSide分頁對象
Limit limit = RequestUtils.getLimit(request);
// 取总记录数
int pageNo = RequestUtils.getPageNo(request);
int pagesize = RequestUtils.getCurrentRowsDisplayed(request);
if (pagesize == 0 )
pagesize = PAGESIZE;
// 设置总记录数及每页记录数
int totalRows = RequestUtils.getTotalRowsFromRequest(request);
if (totalRows <= 0 ) {
totalRows = getEntityManager()
.getCount(getEntityClass(), filterMap);
}
limit.setRowAttributes(totalRows, pagesize);
// 根據參數得到結果
List < Bulletin > result = getEntityManager().queryForListByCriter(
getEntityClass(), filterMap, sortMap,
((pageNo - 1 ) * pagesize), pagesize);
request.setAttribute(getEntityListName(), result);
request.setAttribute( " myPageSize " , getPageSize(request));
request.setAttribute( " type " , v_type);
return mapping.findForward(LIST);
}
* 用ECSide構建列表
*
*/
public ActionForward list(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String v_type = request.getParameter( " type " );
// 0) 設定過濾條件
Map < String, Object > filterMap = new HashMap < String, Object > ();
// filterMap.put("content", "test");
Map < String, Object > sortMap = new HashMap < String, Object > ();
sortMap.put( " createTime " , " desc " ); // 按照創建時間倒序排列
// 1) 設定ECSide分頁對象
Limit limit = RequestUtils.getLimit(request);
// 取总记录数
int pageNo = RequestUtils.getPageNo(request);
int pagesize = RequestUtils.getCurrentRowsDisplayed(request);
if (pagesize == 0 )
pagesize = PAGESIZE;
// 设置总记录数及每页记录数
int totalRows = RequestUtils.getTotalRowsFromRequest(request);
if (totalRows <= 0 ) {
totalRows = getEntityManager()
.getCount(getEntityClass(), filterMap);
}
limit.setRowAttributes(totalRows, pagesize);
// 根據參數得到結果
List < Bulletin > result = getEntityManager().queryForListByCriter(
getEntityClass(), filterMap, sortMap,
((pageNo - 1 ) * pagesize), pagesize);
request.setAttribute(getEntityListName(), result);
request.setAttribute( " myPageSize " , getPageSize(request));
request.setAttribute( " type " , v_type);
return mapping.findForward(LIST);
}
这里我构建了过滤条件及排序条件查询数据,通过queryForListByCriter方法,输入当前起始页及每页的显示条数在数据层得到所需数据。详见代码中的注释。另附数据处理层两个方法的代码:
/**/
/*分页查询数据*/
public List queryForListByCriter(Class entityClass, Map filter,
Map sortMap, int start, int everypage) {
Criteria criteria = getCriteria(entityClass);
setFilter(criteria, filter);
setSort(criteria, sortMap);
criteria.setFirstResult(start);
criteria.setMaxResults(everypage);
return criteria.list();
}
/**/ /*计算数据条数*/
public int getCount(Class entityClass, Map filter) {
Criteria criteria = getCriteria(entityClass);
setFilter(criteria, filter);
criteria.setProjection(Projections.rowCount());
return ((Integer) criteria.uniqueResult()).intValue();
}
public List queryForListByCriter(Class entityClass, Map filter,
Map sortMap, int start, int everypage) {
Criteria criteria = getCriteria(entityClass);
setFilter(criteria, filter);
setSort(criteria, sortMap);
criteria.setFirstResult(start);
criteria.setMaxResults(everypage);
return criteria.list();
}
/**/ /*计算数据条数*/
public int getCount(Class entityClass, Map filter) {
Criteria criteria = getCriteria(entityClass);
setFilter(criteria, filter);
criteria.setProjection(Projections.rowCount());
return ((Integer) criteria.uniqueResult()).intValue();
}
注:ecside与ORM工具无关,不管你使用什么方法只要能获得一个集合就好,这里我用的是Hibernate获得的集合。
3)在JSP中使用ecside
需要注意的是:
1. items的值一定要和request.setAttribute(getEntityListName(), result); 属性一致
2. 可以引用属性名做为值显示,如:${bulletin.id}
3. <ec:column property="name" title="公告名称">property属性值一定是映射文件中的某个属性
<%
@ page contentType = " text/html; charset=UTF-8 "
%>
<% @ taglib uri = " /WEB-INF/ecside.tld " prefix = " ec " %>
<% @ taglib uri = " http://java.sun.com/jsp/jstl/core " prefix = " c " %>
<% @ taglib uri = " http://java.sun.com/jsp/jstl/fmt " prefix = " fmt " %>
<% @ taglib uri = " http://java.sun.com/jsp/jstl/functions " prefix = " fn " %>
< c:set var ="ctx" value ="${pageContext.request.contextPath}" />
< html >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" />
< META HTTP-EQUIV ="pragma" CONTENT ="no-cache" >
< META HTTP-EQUIV ="Cache-Control" CONTENT ="no-cache, must-revalidate" >
< META HTTP-EQUIV ="expires" CONTENT ="0" >
< title > 公告列表 </ title >
< link rel ="stylesheet" type ="text/css" href ="${ctx}/module/bizAcceptance/resources/ecside/css/ecside_style.css" />
< script type ="text/javascript" src ="${ctx}/module/bizAcceptance/resources/ecside/js/prototype_mini.js" ></ script >
< script type ="text/javascript" src ="${ctx}/module/bizAcceptance/resources/ecside/js/ecside.js" ></ script >
< script type ="text/javascript" src ="${ctx}/module/bizAcceptance/resources/ecside/js/ecside_msg_utf8_cn.js" ></ script >
</ head >
< body >
< table width ="100%" border ="0" cellspacing ="0" cellpadding ="0" >
<!-- 校验信息 -->
< tr >
< td class ="left" > <% @ include file = " /module/commons/htmlmessages.jsp " %> </ td >
</ tr >
< tr >
< td height ="30" >
< span style ="align:left;font-size:9pt;" >
請選擇公告
< input type ="button" name ="Submit3" value ='進 入' onclick ="doView()" >
</ span >< br >
</ td >
</ tr >
< tr >
< td >
< ec:table items ="bulletins" var ="bulletin"
retrieveRowsCallback ="limit"
filterRowsCallback ="limit"
action ="${ctx}/module/bulletin.do?method=list&type=${type}"
title ="我的公告列表"
useAjax ="false"
showPrint ="false"
width ="100%"
resizeColWidth ="true"
filterable ="false"
listWidth ="100%"
rowsDisplayed ="${myPageSize}"
pageSizeList ="${myPageSize},10,15,20,all"
xlsFileName ="公告列表.xls"
styleClass ="tableRegion"
style ="border:2px;table-layout:fixed;"
classic ="true" >
< ec:row >
< ec:column property ="_0" title ="選擇" width ="6%" >
< input type ="radio" id ="radio_${GLOBALROWCOUNT}" name ="checkedRadio" value ="${bulletin.id}" >
</ ec:column >
< ec:column property ="_1" title ="序號" width ="6%" >
${GLOBALROWCOUNT}
</ ec:column >
< ec:column property ="name" title ="公告名稱" >
< a href ="JavaScript:doStarting('${affair.id}')" title ="點擊查看" >< c:out value ="${bulletin.name}" /></ a >
</ ec:column >
< ec:column property ="desn" title ="描述" ellipsis ="true" />
< ec:column property ="createBy" title ="創建人" width ="10%" />
< ec:column property ="createTime" title ="創建時間" width ="20%" >
< fmt:formatDate value ="${bulletin.createTime}" pattern ="yyyy-MM-dd HH:mm:ss" />
</ ec:column >
< ec:column property ="_2" title ="可執行操作" >
< a href ="${ctx}/module/bulletin.do?method=edit&ID=${bulletin.id}" >< img src ="${ctx}/images/affairmgt/update.gif" border ="0" title ="編輯" > 編輯 </ a >
< a href ="${ctx}/module/bulletin.do?method=delete&ID=${bulletin.id}" >< img src ="${ctx}/images/affairmgt/delete.gif" border ="0" title ="移除" > 移除 </ a >
</ ec:column >
</ ec:row >
</ ec:table >
</ td >
</ tr >
</ table >
< script language ="javascript" >
var _confirm = " false " ;
var confirmMsg = " 查看此公告? " ;
var urlPrefix = " ${ctx}/module/bulletin.do?method=view&ID= " ;
function doView(itemId) {
if (itemId != null ) {
if (_confirm == ' false ' || confirm(confirmMsg)) {
ShowWaiting('正在加载数据,请稍候');
window.location = urlPrefix + itemId;
}
} else {
var radio = document.getElementsByName('checkedRadio');
for (i = 0 ; i < radio.length; i ++ ) {
if (radio[i].checked) {
if (_confirm == ' false ' || confirm(confirmMsg)) {
itemId = radio[i].value;
ShowWaiting('正在加载数据,请稍候');
window.location = urlPrefix + itemId;
}
return ;
}
}
alert('請選擇一個公告!');
}
}
</ script >
</ body >
</ html >
<% @ taglib uri = " /WEB-INF/ecside.tld " prefix = " ec " %>
<% @ taglib uri = " http://java.sun.com/jsp/jstl/core " prefix = " c " %>
<% @ taglib uri = " http://java.sun.com/jsp/jstl/fmt " prefix = " fmt " %>
<% @ taglib uri = " http://java.sun.com/jsp/jstl/functions " prefix = " fn " %>
< c:set var ="ctx" value ="${pageContext.request.contextPath}" />
< html >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" />
< META HTTP-EQUIV ="pragma" CONTENT ="no-cache" >
< META HTTP-EQUIV ="Cache-Control" CONTENT ="no-cache, must-revalidate" >
< META HTTP-EQUIV ="expires" CONTENT ="0" >
< title > 公告列表 </ title >
< link rel ="stylesheet" type ="text/css" href ="${ctx}/module/bizAcceptance/resources/ecside/css/ecside_style.css" />
< script type ="text/javascript" src ="${ctx}/module/bizAcceptance/resources/ecside/js/prototype_mini.js" ></ script >
< script type ="text/javascript" src ="${ctx}/module/bizAcceptance/resources/ecside/js/ecside.js" ></ script >
< script type ="text/javascript" src ="${ctx}/module/bizAcceptance/resources/ecside/js/ecside_msg_utf8_cn.js" ></ script >
</ head >
< body >
< table width ="100%" border ="0" cellspacing ="0" cellpadding ="0" >
<!-- 校验信息 -->
< tr >
< td class ="left" > <% @ include file = " /module/commons/htmlmessages.jsp " %> </ td >
</ tr >
< tr >
< td height ="30" >
< span style ="align:left;font-size:9pt;" >
請選擇公告
< input type ="button" name ="Submit3" value ='進 入' onclick ="doView()" >
</ span >< br >
</ td >
</ tr >
< tr >
< td >
< ec:table items ="bulletins" var ="bulletin"
retrieveRowsCallback ="limit"
filterRowsCallback ="limit"
action ="${ctx}/module/bulletin.do?method=list&type=${type}"
title ="我的公告列表"
useAjax ="false"
showPrint ="false"
width ="100%"
resizeColWidth ="true"
filterable ="false"
listWidth ="100%"
rowsDisplayed ="${myPageSize}"
pageSizeList ="${myPageSize},10,15,20,all"
xlsFileName ="公告列表.xls"
styleClass ="tableRegion"
style ="border:2px;table-layout:fixed;"
classic ="true" >
< ec:row >
< ec:column property ="_0" title ="選擇" width ="6%" >
< input type ="radio" id ="radio_${GLOBALROWCOUNT}" name ="checkedRadio" value ="${bulletin.id}" >
</ ec:column >
< ec:column property ="_1" title ="序號" width ="6%" >
${GLOBALROWCOUNT}
</ ec:column >
< ec:column property ="name" title ="公告名稱" >
< a href ="JavaScript:doStarting('${affair.id}')" title ="點擊查看" >< c:out value ="${bulletin.name}" /></ a >
</ ec:column >
< ec:column property ="desn" title ="描述" ellipsis ="true" />
< ec:column property ="createBy" title ="創建人" width ="10%" />
< ec:column property ="createTime" title ="創建時間" width ="20%" >
< fmt:formatDate value ="${bulletin.createTime}" pattern ="yyyy-MM-dd HH:mm:ss" />
</ ec:column >
< ec:column property ="_2" title ="可執行操作" >
< a href ="${ctx}/module/bulletin.do?method=edit&ID=${bulletin.id}" >< img src ="${ctx}/images/affairmgt/update.gif" border ="0" title ="編輯" > 編輯 </ a >
< a href ="${ctx}/module/bulletin.do?method=delete&ID=${bulletin.id}" >< img src ="${ctx}/images/affairmgt/delete.gif" border ="0" title ="移除" > 移除 </ a >
</ ec:column >
</ ec:row >
</ ec:table >
</ td >
</ tr >
</ table >
< script language ="javascript" >
var _confirm = " false " ;
var confirmMsg = " 查看此公告? " ;
var urlPrefix = " ${ctx}/module/bulletin.do?method=view&ID= " ;
function doView(itemId) {
if (itemId != null ) {
if (_confirm == ' false ' || confirm(confirmMsg)) {
ShowWaiting('正在加载数据,请稍候');
window.location = urlPrefix + itemId;
}
} else {
var radio = document.getElementsByName('checkedRadio');
for (i = 0 ; i < radio.length; i ++ ) {
if (radio[i].checked) {
if (_confirm == ' false ' || confirm(confirmMsg)) {
itemId = radio[i].value;
ShowWaiting('正在加载数据,请稍候');
window.location = urlPrefix + itemId;
}
return ;
}
}
alert('請選擇一個公告!');
}
}
</ script >
</ body >
</ html >
其中,<ec:column property="desn" title="描述" ellipsis="true" />,ellipsis属性实现单元格内数据过长的时候,自动截短并加"..."的功能,但是ie only!因为ff不支持 text-overflow: ellipsis; 使用ellipsis="true"的同时,还要为ec:table加上 style="table-layout:fixed;" (如果您已经使用了调整列宽功能 则不用添加)。