转了几篇文章。书名号里面的是我自己加上去的。
DisplayTag外部(External)分页如何导出全部数据
2010-06-25 11:13
http://wallimn.javaeye.com/blog/421465
最近大量使用了displayTag标签,真是很好用,各种功能设计得很体贴、很实用,效率也不错。导出、分页、排序都很方便,外
观设计也很便于修改。
对于大数据量的分页与排序,一般推荐使用外部(External)排序分页(详细介绍请看我翻译的官方文档:
http://wallimn.javaeye.com/blog/327753),也就是使用分页查询的SQL语句,利用数据库直接处理好分页与排序,服务器端
servlet只处理当前页的数据。详细方法请见我的博客:
http://wallimn.javaeye.com/blog/327742
http://wallimn.javaeye.com/blog/327741
但是,当使用这种方式的时候,导出为Excel等数据的时候,无法导出全部数据。在不使用外部方式的时候,在属性文件里设
置一个参数(export.amount),或者在标签中设置一个参数,就可以实现全部数据的导出。
这个问题该如何解决呢?
其实当使用外部分页的时候,由于此时List中只有当前页的数据,正常来讲是无法导出全部数据。问题的关键就是如何让后
台的servlet知道用户的请求是导出数据。注意到,在导出的时候,DisplayTag标签会使用一个地址栏参数来传递导出的类型,这
个参数的名称很怪,是个数字与字母的组合。查阅了一下文档及源码,发现这实际上displayTag定义的一个常量:
TableTagParameters.PARAMETER_EXPORTING。任何时候传递导出类型的时候都使用这个参数名。这样我们就可以在服务器端通过
判断这个参数的有无,来知道用户的请求是分页展示数据,还是导出数据。若是导出,那么可以将分页SQL语句特殊处理一下,将
全部数据返回。然后displayTag就自动将其全部导出为用户指定的类型了。
以上说明了解决DisplayTag外部(External)分页如何导出全部数据的大致思路,希望对使用过这个标签遇到这个问题网友有
所帮助。
2009-07-16
注:
如果还不行,可以试着将每页的记录数设置为全部记录的总数。
《《《《《《《《《《《《《《《《《《《《
我做做好事,给个例子哈,看大家那么辛苦~~~~~~
这是我用struts2做的外部分页action类(起名叫做StandardPageAction)中的execute方法,大家管中窥豹:
public String execute() {
try{
StandardDAO dao=new StandardDAO();
final int pageSize = 15;这里确定页大小。在实际应用时,页大小最好在此处确定。
// 获取当前页码,displaytag通过参数"page"传递这个值
int pageNumber;
if (request.getParameter("page") != null
&& !"".equals(request.getParameter("page"))) {
pageNumber = Integer.parseInt(request.getParameter("page"));
} else {
pageNumber = 1;
}
StandardPageList pageList = new StandardPageList();
//Test:中文数据,即猪;Test1:数字数据,即1;
hql1 = "from Test"; //注意:这里使用的Test,即类名,而非数据库名test。面向对象!!!!!!!!!
//由于是使用外部分页,所以在这里考虑导出全部数据的处理。判断请求是否含有“导出”参数。
Object p = request.getParameter(TableTagParameters.PARAMETER_EXPORTING);
List pages = null;
if(p!=null){//导出数据时,导出所有数据。
pages = dao.getAllData(hql1);
}
else //非导出数据时,按照外部分页的要求,仅提取一页的数据用于显示。
pages = dao.getData(pageNumber,pageSize,hql1);//hql1需通过外部使用setter设值,可参照上面的hql语句。。
。。
// 设置当前页码
pageList.setPageNumber(pageNumber);
// 设置当前页列表
pageList.setList(pages);
// 设置page size
pageList.setObjectsPerPage(pageSize);
// 设置总页数
hql2 = "select count(*) from Test";//注意:这里使用的Test,即类名,而非数据库名test。面向对象!!!!!!
!!!
pageList.setFullListSize(dao.getDataSize(hql2));//hql2需通过外部使用setter设值,可参照上面的hql语句。。。
。
//设置pageList给页面中的displaytag的table标签以显示结果。
request.setAttribute("pageList", pageList);
}catch(NullPointerException ex){
System.out.println("注意:你没给hql1、hql2赋值!!!!!!!!!!!!");
}
return SUCCESS;
}
这两个类都是要自己去实现的,没办法,外部分页大部分都是这样子去做的:
StandardDAO//负责执行hql语句。
StandardPageList//实现了PaginatedList接口
另外提醒一下,上面的hql1、hql2语句嘛,本来赋值不应在action里面直接赋值的,最好是由外部setter来注入值(=。= 够专业
吧~~~~~~~~)。我这里因为是测试,所以贪方便了。没办法啦,这几天一直在弄displaytag,研究完毕,测试完毕后就能大范围
应用到我的项目里了。
大家仔细看完最近发的博文就知道了。
话说大家要有自己的想法,不要只知道copy、paste,大家要多写写博文,多多交流,多为后来人指路~~~~~~
这里是“开源的世界”open source~~~~~~~
》》》》》》》》》》》》》》》》》》》》》
《《《《《《《《《《《《《《《《《《《《《
后记:后来由于相关的项目需要,所以又加上了一些东西,比如设计了一个tableDecorator(实现了
org.displaytag.decorator.TableDecorator),还有前面提到的hql1、hql2需要在外部设置值的问题。。。所以进行了一些尝试
。。。起初我想用一个新的action:NewAction,从它那里设置hql1、hql2,然后跳转到StandardPageAction。。。但是实践证明
这样并不成功。。。
在思考中,想到了一个方法,就是“继承”,用NewAction继承StandardPageAction,然后直接使用NewAction,这样就不需要分
几步跳转了。。。能够有效地实现效果。。。同理,由于不同的需要,也可以设计各种NewTableDecorator来达到不同的显示效果
。我把这种处理方案称之为“定制”设计。(注:TableDecorator可以用来给生成的列表添加一些自定义的列,比如用于增删改
查的链接)
当然,后来我还想了一下,我可以把参数传到action中的实例变量去,网上也有相应的方法。这样就能达到一个action,多次复
用,从而可以有不同效果的目的。但是后来想了一下,担心过于机械化了,而且参数可能会太多,所以终究没有采纳。。。
》》》》》》》》》》》》》》》》》》》》》》
关于使用displaytag导出时的若干问题
问题:当export="list" 时不能到全部导出.
解决方法:
修改TableTag.java
doExport()
在 boolean exportFullList = this.properties.getExportFullList();
后添加以下代码:
if (exportFullList) {
this.tableModel.setRowListPage(this.tableModel.getRowListFull());
}
出现乱码的地方有三个地方,当导出中文列表名,中文表格数据和导出文件名时,会产生乱码现象。
解决方法:
更改配置文件displaytag.properties,使用displaytag-export-poi.jar包。更改
export.excel.class=org.displaytag.export.ExcelView 为 export.excel.class=org.displaytag.excel.ExcelHssfView,这
样可以解决中文表格数据的问题。对于中文列表名乱码的问题,必须更改org.displaytag.excel.ExcelHssfView源代码。具体如
下:
原来:
HSSFCell cell = xlsRow.createCell((short) colNum++);
cell.setCellValue(columnHeader);
cell.setCellStyle(headerStyle);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
改为:
HSSFCell cell = xlsRow.createCell((short) colNum++);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(columnHeader);
cell.setCellStyle(headerStyle);
导出文件名:
TableTag.java
原来:
if (StringUtils.isNotEmpty(filename))
{
response.setHeader("Content-Disposition", //$NON-NLS-1$
"attachment; filename=\"" + filename + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
改为:
if (StringUtils.isNotEmpty(filename)) {
response
.setHeader(
"Content-Disposition", //$NON-NLS-1$
"attachment; filename=" + new String(filename.getBytes("gb2312"), ("ISO8859-1"))); //$NON-NLS-1$ //$NON-
NLS-2$
}
2009-07-16
关于displaytag external paging 第二种分页方法导出所有数据的问题
首先要感谢zuiyanwangyue提供给我的解决方法!!!
我是采用了displaytag提供的第二种分页方法
// 页数的参数名
String pageIndexName = new ParamEncoder(Constants.ABSENCE_LIST)
.encodeParameterName(TableTagParameters.PARAMETER_PAGE);
// 每页显示的条数
int pageSize = 15;
// 当前页
int pageIndex = GenericValidator.isBlankOrNull(request.getParameter(pageIndexName)) ? 0 : (Integer.parseInt
(request.getParameter(pageIndexName)) - 1);
// 统计总记录数
int resultSize = (Integer) absMgr.getPypDepartmentAbsByTimesCount(condition[0], condition[1], condition[2]).get
(0);
//获取导出的状态如果不为空.说明点击了导出按钮
String exportValue = request.getParameter(TableTagParameters.PARAMETER_EXPORTING);
if (exportValue == null || exportValue.equals("")) {
// 取得当前分页数据
studentAbsList = absMgr.getPypDepartmentAbsByTimesSql(pageIndex, pageSize, condition[0], condition[1], condition
[2]);
}else {
//获取所有数据
studentAbsList = absMgr.fastGetDepAbs(condition);
}
//缺勤信息
request.setAttribute(Constants.ABSENCE_LIST, studentAbsList);
我觉得你说的问题可能和Displaytag的设计初衷有关,如果是一个特殊的列表,亦即table标签中的partialList="true",那么
Table标签的处理类在进行初始化参数时(见TableTag的initParameters()方法),会做出相应的处理使得在页面上看到的数据和导
出的数据条数是一样的,它并没有区别对待不同的媒体类型。
见TableTag的1065以及1066两行:
PaginationHelper paginationHelper = new PaginationHelper(pageNumber, pagesize);
this.tableIterator = paginationHelper.getIterator(this.list);
如果想要Displaytag适合你的要求恐怕就要修改Displaytag的源代码了,增加以下判断:
//检查当前的媒体类型
if(MediaTypeEnum.HTML.equals(this.currentMediaType)){
PaginationHelper paginationHelper = new PaginationHelper(pageNumber, pagesize);
this.tableIterator = paginationHelper.getIterator(this.list);
}else {
this.tableIterator = IteratorUtils.getIterator(this.list);
}
即如果是在页面上显示则进行分页,否则的话就遍历整个列表。
这样就应该满足你的要求了。
帮我解决此问题的人是zuiyanwangyue
一下是他的博客地址
http://zuiyanwangyue.javaeye.com/
真的非常感谢他.因为本人还是学生...代码量不多.看了源代码3天了,还是一点头绪都没有.
今天收到zuiyanwangyue发来的消息.尝试改了一下源代码.结果行了.在这里再一次感谢zuiyanwangyue.谢谢!!!