- 浏览: 389084 次
- 性别:
- 来自: 合肥
文章分类
- 全部博客 (314)
- java (132)
- 生活 (13)
- javase模式 (6)
- weblogic (4)
- jquery (5)
- sql (21)
- ecside (1)
- el (3)
- css (5)
- spring (7)
- ireport (2)
- linux (14)
- struts2 (2)
- jstl (1)
- rmi (1)
- rose (9)
- js (6)
- swing (4)
- webservice (1)
- jboss (1)
- ejb3 (2)
- xml (1)
- 线程 (9)
- socket (3)
- jms (2)
- tomcat (10)
- 领域驱动 (3)
- json (3)
- 权限 (2)
- jvm (1)
- 书籍 (1)
- eclipse RCP (0)
- 数据库设计 (10)
- 软件分析建模 (5)
- 分析建模 (3)
- hibernate jpa (5)
- Java 获取系统信息,包括CPU使用率、硬盘大小、网卡状态、系统信息等 (1)
- 项目管理 (2)
- 财务 (0)
- oracle (2)
- 需求 (2)
- rcp gef (0)
- c++ (1)
- hadoop (2)
- BIGDATA (3)
- c (6)
最新评论
-
lh_kevin:
...
jpa 注解 -
一别梦心:
你好,我也遇到此问题了。就你贴的那段代码,你说了两种解决方式, ...
Hibernate的Antlr在Weblogic中产生Jar冲突的历史缘故以及解决办法 -
fireinjava:
...
el表达式 -
宋建勇:
...
JSON: property "xxx" has no getter method in class "..." -
handawei:
有道理,jpa是orm框架的java标准,它关注的是对象到关系 ...
jpa 注解
displaytag数据库分页方法及导出数据的问题处理
文章分类:Java编程
最近在使用 springside 配合 struts2 + spring2.5 + hibernate3 做项目,为了不重复发明轮子(其实是懒,而且项目时间有限),使用到了 displaytag 作为页面显示的组件。 displaytag 具有分页显示,导出报表,页面排序等功能。与其相似的还有另外一个工具叫做 extremecomponent 。虽然 displaytag 功能很多,但是也有很多问题:第一就是他的默认分页和排序是基于内存分页的,这个在实际项目中是不太可行的,所以需要修改。第二就是他的导出报表的功能,他主要能导出 5 种格式 csv , xls , xml , pdf , rtf (主要是 pdf 和 excel ),其中默认的 pdf 和 excel 导出都有乱码问题。
本文主要是讲述如何解决这 2 个问题。
displaytag 官网: http://displaytag.sourceforge.net/1.2/
基本的配置和使用你可以从官网上了解到,本文不做说明。
本文的解决方法一部分是来自于网络其他文章。
好了首先是第一个分页问题,我们要使 displaytag 能够用数据库分页,而不仅仅是内存分页。 displaytag 其实已经提供了 2 种方法让你实现数据库,在其官网中有介绍
http://displaytag.sourceforge.net/1.2/tut_externalSortAndPage.html
我使用的是第一种实现,实现 displaytag 的 PaginatedList 接口:
- import java.util.List;
- import org.displaytag.pagination.PaginatedList;
- import org.displaytag.properties.SortOrderEnum;
- import org.springside.modules.orm.Page;
- /**
- * 实现displaytag的数据库的分页接口
- * 并集成springside的Page类,
- * 这样可以同时使用 springside的数据库分页功能及displaytag的分页显示功能
- * @author tianjl
- *
- * @param <T>
- */
- public class DBPaginatedList<T> extends Page<T> implements PaginatedList {
- private SortOrderEnum sortDirection = SortOrderEnum.ASCENDING;
- private String sortCriterion;
- // -- 构造函数 --//
- public DBPaginatedList() {
- super();
- }
- public DBPaginatedList(int pageSize) {
- super(pageSize);
- }
- public int getFullListSize() {
- return (int) totalCount;
- }
- public List<T> getList() {
- return result;
- }
- public int getObjectsPerPage() {
- return pageSize;
- }
- public int getPageNumber() {
- return pageNo;
- }
- public void setSortCriterion(String fieldN) {
- this.sortCriterion = (fieldN == null || "null".equals(fieldN)) ? "1"
- : fieldN;
- }
- public String getSortCriterion() {
- return this.sortCriterion;
- }
- public void setSortDirection(String dir) {
- if (dir == null || "null".equals(dir) || "asc".equalsIgnoreCase(dir)) {
- sortDirection = SortOrderEnum.ASCENDING;
- } else {
- sortDirection = SortOrderEnum.DESCENDING;
- }
- }
- public void setSortDirection(SortOrderEnum sortDirection) {
- this.sortDirection = sortDirection;
- }
- public String getSortDirectionStr() {
- if (sortDirection == SortOrderEnum.ASCENDING)
- return "ASC";
- else
- return "DESC";
- }
- public SortOrderEnum getSortDirection() {
- return sortDirection;
- }
- public String getSearchId() {
- return Integer.toHexString(pageSize * 10000 + pageNo);
- }
- }
import java.util.List; import org.displaytag.pagination.PaginatedList; import org.displaytag.properties.SortOrderEnum; import org.springside.modules.orm.Page; /** * 实现displaytag的数据库的分页接口 * 并集成springside的Page类, * 这样可以同时使用 springside的数据库分页功能及displaytag的分页显示功能 * @author tianjl * * @param <T> */ public class DBPaginatedList<T> extends Page<T> implements PaginatedList { private SortOrderEnum sortDirection = SortOrderEnum.ASCENDING; private String sortCriterion; // -- 构造函数 --// public DBPaginatedList() { super(); } public DBPaginatedList(int pageSize) { super(pageSize); } public int getFullListSize() { return (int) totalCount; } public List<T> getList() { return result; } public int getObjectsPerPage() { return pageSize; } public int getPageNumber() { return pageNo; } public void setSortCriterion(String fieldN) { this.sortCriterion = (fieldN == null || "null".equals(fieldN)) ? "1" : fieldN; } public String getSortCriterion() { return this.sortCriterion; } public void setSortDirection(String dir) { if (dir == null || "null".equals(dir) || "asc".equalsIgnoreCase(dir)) { sortDirection = SortOrderEnum.ASCENDING; } else { sortDirection = SortOrderEnum.DESCENDING; } } public void setSortDirection(SortOrderEnum sortDirection) { this.sortDirection = sortDirection; } public String getSortDirectionStr() { if (sortDirection == SortOrderEnum.ASCENDING) return "ASC"; else return "DESC"; } public SortOrderEnum getSortDirection() { return sortDirection; } public String getSearchId() { return Integer.toHexString(pageSize * 10000 + pageNo); } }
这里要讲一下, Page 类是 springside 提供的对分页功能的封装。这里你应该去掉继承 Page 类,并配合你自己的数据库分页功能。在 Page 类中,有一个内部的 List 对象,存放着真实的结果集数据。 displaytag 在分析时,会判断你传给他的对象是否实现了 PaginatedList 接口,如果实现了,它会从该对象中调用 getList() 方法,获取结果集。所以在你的使用中,你应该注意你的数据库分页代码和 PaginatedList 接口的实现类的配合。
- public interface PaginatedList{
- /**
- * 获取分页的结果集
- */
- List getList();
- /**
- * 获取当前页数
- */
- int getPageNumber();
- /**
- * 获取每页的个数
- */
- int getObjectsPerPage();
- /**
- * 获取整个结果集的个数
- */
- int getFullListSize();
- /**
- * 获取根据哪一列排序
- */
- String getSortCriterion();
- /**
- * 升序还是降序
- */
- SortOrderEnum getSortDirection();
- /**
- * 返回一个查询的id
- */
- String getSearchId();
- }
public interface PaginatedList{ /** * 获取分页的结果集 */ List getList(); /** * 获取当前页数 */ int getPageNumber(); /** * 获取每页的个数 */ int getObjectsPerPage(); /** * 获取整个结果集的个数 */ int getFullListSize(); /** * 获取根据哪一列排序 */ String getSortCriterion(); /** * 升序还是降序 */ SortOrderEnum getSortDirection(); /** * 返回一个查询的id */ String getSearchId(); }
这里请注意,你的数据库分页代码和 displaytag 的分页其实是 2 个不同的实现,也就是说,你在之后的使用中,要同时为你数据库分页的代码设置分页值,排序值,并且也要为 PaginatedList 接口的实现类设置分页值及排序值。 当然你如果设计的好,能将 2 者柔和在一起,你可以只设置一次。我这里还是设置 2 次值的。 我这里写了个工具类还是设置 2 次值的。他从request中获取分页参数,放到 PaginatedList 的实现类中,实际的数据库分页参数由struts2自动封装到action中的Page对象中,其实这个类写的有些多余,完全可以在 PaginatedList 的实现类内部解决问题,根本不需要引入HttpServletRequest 。
- /**
- * 分页工具类
- *
- * @author tianjl
- *
- */
- public class PaginationUtil {
- /**
- * 该方法用于displaytag的参数到springside的page的分页参数做转换
- *
- * @param request
- * (HttpServletRequest) 用于获取请求参数
- * @param page
- * (DBPaginatedList) springside的Page对象
- */
- public static void pageInfoPopulate(HttpServletRequest request,
- DBPaginatedList page) {
- if (request == null || page == null)
- return;
- else {
- String pagestr = request.getParameter("page");
- String sort = request.getParameter("sort");
- String dir = request.getParameter("dir")
- if (!StringUtils.isBlank(pagestr)) {
- page.setPageNo(NumberUtils.toInt(pagestr));
- }
- if (!StringUtils.isBlank(sort)) {
- page.setOrderBy(sort);
- page.setSortCriterion(sort);
- }
- if (!StringUtils.isBlank(dir)) {
- if (StringUtils.equals(Page.ASC, dir)) {
- page.setOrder(Page.ASC);
- } else {
- page.setOrder(Page.DESC);
- }
- page.setSortDirection(dir);
- }
- }
- }
- }
/** * 分页工具类 * * @author tianjl * */ public class PaginationUtil { /** * 该方法用于displaytag的参数到springside的page的分页参数做转换 * * @param request * (HttpServletRequest) 用于获取请求参数 * @param page * (DBPaginatedList) springside的Page对象 */ public static void pageInfoPopulate(HttpServletRequest request, DBPaginatedList page) { if (request == null || page == null) return; else { String pagestr = request.getParameter("page"); String sort = request.getParameter("sort"); String dir = request.getParameter("dir") if (!StringUtils.isBlank(pagestr)) { page.setPageNo(NumberUtils.toInt(pagestr)); } if (!StringUtils.isBlank(sort)) { page.setOrderBy(sort); page.setSortCriterion(sort); } if (!StringUtils.isBlank(dir)) { if (StringUtils.equals(Page.ASC, dir)) { page.setOrder(Page.ASC); } else { page.setOrder(Page.DESC); } page.setSortDirection(dir); } } } }
然后页面中写上displaytag的标签:
- <display:table id="content" name="pageList" requestURI="/security/user.do"
- size="totalCount" pagesize="${pageList.pageSize }" partialList="true">
- <display:column property="id" sortable="true" style="width:2%"/>
- <display:column property="name" title="姓名" sortable="true" />
- <display:column property="loginName" title="登录名" sortable="true" />
- <display:column property="email" title="邮箱" sortable="true" />
- </display:table>
<display:table id="content" name="pageList" requestURI="/security/user.do" size="totalCount" pagesize="${pageList.pageSize }" partialList="true"> <display:column property="id" sortable="true" style="width:2%"/> <display:column property="name" title="姓名" sortable="true" /> <display:column property="loginName" title="登录名" sortable="true" /> <display:column property="email" title="邮箱" sortable="true" /> </display:table>
这里有几个点要注意, size 属性中必须指定一个总页数,而且必须是 int 型的, springside 中 Page 类的总页数是 long 型的,所以我又自己定义了个 totalCount ,将值给 size 属性。 partialList 属性必须指定为 true ,这样 displaytag 才会使用你的分页。
到这里已经可以使 displaytag 使用你提供的数据库分页了。
然后,我们来解决导出数据的问题。导出数据是个很常用的功能,基本上是个系统都要这个功能。 displaytag 是提供了该功能的,但是问题太多。一个是当你让 displaytag 使用了数据库分页后,只能导出当前页的数据;另一个问题是导出数据中文乱码的问题。
第一个问题需要修改源代码,给与实际解决方案文章在此:
http://superwing.iteye.com/blog/427407
你需要在 org.displaytag.tags.TableTag.java 中,将 1065 以及 1066 两行进行替换:
将
- PaginationHelper paginationHelper = new PaginationHelper(pageNumber, pagesize);
- this.tableIterator = paginationHelper.getIterator(this.list);
PaginationHelper paginationHelper = new PaginationHelper(pageNumber, pagesize); this.tableIterator = paginationHelper.getIterator(this.list);
替换为:
- 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);
- }
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); }
在你的 action 种的代码中,你需要知道用户是否点击了导出超链接,通过以下代码可以获取该值:
String exportValue = request.getParameter(TableTagParameters.PARAMETER_EXPORTING);
如果该值不为空,则表示用户按了导出,否则就是没有。你应该根据此值来选择是查询部分内容还是全部内容。比如:
- if (exportValue == null || exportValue.equals("")) {
- //非导出,根据查询条件filters进行分页查询
- pageList = securityEntityManager.searchUser(pageList, filters);
- } else {
- //导出,根据查询条件filters查询出所有结果集
- List<User> userList = securityEntityManager.getAllUser(pageList, filters);
- pageList.setResult(userList);
- }
if (exportValue == null || exportValue.equals("")) { //非导出,根据查询条件filters进行分页查询 pageList = securityEntityManager.searchUser(pageList, filters); } else { //导出,根据查询条件filters查询出所有结果集 List<User> userList = securityEntityManager.getAllUser(pageList, filters); pageList.setResult(userList); }
好,第一个导出问题解决完毕。
接下去是乱码问题,我这里只说明 excel 和 pdf 的处理。解决方法也是来自于网络。
excel 的导出处理相对简单,在你项目的 classpath 中加入 displaytag.properties 文件,加入以下代码即可。
export.excel.class=org.displaytag.export.excel.ExcelHssfView
注意该属性表示使displaytag使用poi导出excel,所以你需要加入displaytag-export-poi-1.2.jar和poi的jar包,而且只能使用poi3.2版本的jar包,其他版本都会报错说NoSuchMethod,但是我看poi源码,明明是有该方法的,不知道什么原因。(我使用过poi3.5和poi3.0都报了该错)
pdf的乱码处理,需要下载iTextAsian.jar,然后加入你的classpath,再修改源代码org.displaytag.export.PdfView的115行处:
- //将
- smallFont = FontFactory.getFont(FontFactory.HELVETICA, 7, Font.NORMAL, new Color(0, 0, 0));
- //替换为:
- smallFont = FontFactory.getFont("STSong-Light","UniGB-UCS2-H", Font.DEFAULTSIZE);
//将 smallFont = FontFactory.getFont(FontFactory.HELVETICA, 7, Font.NORMAL, new Color(0, 0, 0)); //替换为: smallFont = FontFactory.getFont("STSong-Light","UniGB-UCS2-H", Font.DEFAULTSIZE);
这样pdf乱码也可以解决了。
最后再引申几个我遇到的其他问题:
excel导出的内容标题看不清,这个需要修改源码,找到org.displaytag.export.excel.ExcelHssfView的101到107行处是设置标题样式的,主要是把102行:
- //将
- headerStyle.setFillPattern(HSSFCellStyle.FINE_DOTS);
- //替换为:
- headerStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
//将 headerStyle.setFillPattern(HSSFCellStyle.FINE_DOTS); //替换为: headerStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
这样,导出的标题就不会看不清了。
另外一个问题,是因为displaytag和struts2一起使用导致的,由于displaytag生成的参数中带“-”,而struts2中接受的参数中默认又不允许有“-”,控制台会报错,但是却不影响使用。不过控制台老报错,看着也不爽。
在http://hi.baidu.com/j2ee_cn/blog/item/688a03db5a48846cd1164e66.html
说修改xwork源码可以解决该问题,我照做确实解决了,但是又出现了其他问题,struts2不会替我自动封装参数到action的对象中了,所以我又改了回来。大家如果用的也是struts2可以试试,是不是有这样的问题。
另一个方法是只要将,devMode设置为false就不会报这个错了,这个的确可以解决该问题。
发表评论
-
字符串,Volatile
2013-03-18 12:01 1133转载:http://www.ibm.com/de ... -
qian rushi
2012-12-01 10:13 0唐攀,华清远见高级研 ... -
110道 C语言 题目 超经典中的经典
2012-10-21 08:57 0... -
LOG4J
2012-08-07 10:34 1044long4j配置 转载:http://www.iteye. ... -
jpa 注解
2011-12-20 09:23 11840转:http://blog.csdn.net/gdweijin ... -
jna
2011-11-29 17:28 1541... -
eclipse设置
2011-11-16 08:45 869转:http://www.iteye.com/topic/11 ... -
深入分析 Java I/O 的工作机制
2011-11-14 08:57 895... -
java获得计算机信息
2011-10-29 13:03 1376采用singar.jar实现,需要将sigar-x86-win ... -
java内存机制
2011-10-24 13:01 1286转. Java内存机制详解 Ja ... -
缓存技术
2011-09-27 13:28 822一个培训的ppt,是介绍缓存知识的。有兴趣的可以参考:缓存技术 ... -
单点登录
2011-09-26 08:37 1603了解单点登录:: 可以使 ... -
继承和组合的关系
2011-08-18 09:17 913个人工作的感触: 首先框架的编写是难度很大,而工具 ... -
导入导出,创建databaselink
2011-08-10 15:56 2145pl/sql导出表结构和表 ... -
小结一下
2011-08-04 10:20 882觉得程序层面上是:数据类型(int long string) ... -
分析建模
2011-07-17 20:13 874系统建模与分析。 -
Java浮点数的精确计算
2011-06-27 16:10 1001... -
异常系统
2011-05-31 17:19 722http://www.iteye.com/topic/7217 ... -
权限管理
2011-01-27 09:30 1344... -
jvisualvm
2011-01-11 21:09 927可以查看远程 本地的jvm 有两种方式 jmx jstatd ...
相关推荐
它简化了在 JSP 页面中处理数据表的复杂性,提供了丰富的定制选项。以下是对 Displaytag 实现分页的详细解释: 1. **下载与配置 Displaytag** - 首先,你需要从官方网站 (http://displaytag.sourceforge.net) 下载...
DisplayTag 是一个强大的开源Java Web开发中的表格和分页标签库,它提供了许多高级功能,如排序、分页、国际化支持、导出等,能够帮助开发者更方便地处理表格展示和数据分页的问题。以下是对DisplayTag分页及属性的...
DisplayTag是个很好的jsp标签,目前最新版本为1.2,支持了自定义分页,解决了之前版本每次查询都把全部数据查出的低效率做法。但是DisplayTag默认是通过url传参,以及分页导航不灵活给人们带来了不少麻烦。鉴于此...
Hibernate 是一个对象关系映射(ORM)框架,它简化了数据库操作,将数据库表与Java类映射,允许开发者使用面向对象的方式来处理数据。在"Displaytag dwr 分页"的应用中,Hibernate 可能被用来从数据库中检索和操作...
在这个例子中,`repository.getPage()`方法负责处理分页查询,`repository.getTotalPages()`计算总页数。 在前端,DisplayTag 自动处理分页链接的生成,你只需通过`display:table`的属性控制其显示。例如,可以使用...
1. **基本功能**:DisplayTag支持分页、排序、导出数据、自定义样式等多种功能,极大地简化了网页表格的开发工作。通过简单的标签和属性设置,开发者可以轻松创建复杂表格。 2. **标签库**:DisplayTag基于JSTL标签...
Displaytag是一个开源的Java库,专门用于创建复杂的...对于处理大量数据的Web应用,Displaytag的分页、排序和导出功能尤其实用。正确地集成和使用Displaytag,可以帮助开发者更专注于业务逻辑,而不是表格的呈现细节。
- `Action类`:处理业务逻辑,如查询数据、分页、导出Excel。 - `JSP页面`:显示查询结果和分页控件,使用jQuery与服务器通信。 - `DAO(数据访问对象)`:与数据库交互的接口和实现类。 - `模型类`:对应数据库...
DisplayTag作为一款功能强大的标签库,为JSP页面上的Table提供了丰富的处理手段,包括分页、数据导出、分组、列排序等特性,极大地简化了开发者的工作流程,提升了数据展示的灵活性和用户体验。 #### DisplayTag...
“支持直接生成excel等格式”是指DisplayTag具有导出功能,用户可以将表格数据导出为Excel文件,方便进一步的数据处理或分析。这对于需要将大量数据导出到电子表格的应用场景非常有用。导出过程是自动化的,用户只需...
2. **数据处理**:DisplayTag 不仅负责表格的显示,还处理数据的检索和格式化。它可以通过简单的配置与各种数据源(如Hibernate、JDBC)集成,对数据进行分组、过滤和计算。 3. **可扩展性**:DisplayTag 具有良好...
6. **数据源处理**:DisplayTag不仅限于数据库,也可以处理任何可迭代的数据源,如集合或数组。它可以与Spring、Hibernate等框架无缝集成,简化数据绑定过程。 7. **列控制**:DisplayTag支持列的选择和隐藏,用户...
它提供了许多高级特性,如分页、排序、国际化支持、导出功能等,极大地简化了开发人员在Web应用中处理复杂表格的需求。在使用DisplayTag时,需要依赖一些特定的JAR(Java Archive)文件来运行和构建项目。 本压缩包...
4. **下载功能**:DisplayTag支持导出表格数据到各种格式,如CSV、Excel或PDF,使得用户可以方便地保存和共享数据。 5. **国际化与本地化**:DisplayTag支持多种语言,可以根据用户浏览器的设置自动调整标签的文本...
以下是对DisplayTag标签、源码、实例及常见问题的详细解释: 1. **DisplayTag标签**: DisplayTag提供了一系列的JSP标签,如`<display:table>`、`<display:column>`、`<display:export>`等,这些标签用于构建动态...
3. **数据处理**:在对应的Action类中,你需要编写代码来获取并处理数据,这可能涉及到数据库查询或其他数据源操作。 4. **样式和模板**:可能还包括CSS文件和HTML模板,用于定义表格的外观和布局。 学习这个例子时...
1. **分页**:DisplayTag自动处理数据的分页,无需在后端编写复杂的分页逻辑。它可以根据设定的页面大小和当前页数,自动请求数据库获取相应范围的数据。 2. **排序**:用户可以通过点击列头对表格进行排序,...
5. **显示结果**:DisplayTag会自动处理分页逻辑,生成分页链接,并在页面上显示数据。 示例JSP代码: ```jsp <%@ taglib uri="http://displaytag.sourceforge.net/tags" prefix="display" %> 列1"/> 列2"/> ``...
6. **数据源绑定**:DisplayTag可以绑定到各种数据源,如List、Map、数据库结果集等,只需将数据源对象设置到请求或session作用域中。 7. **自定义列**:使用`<display:column>`的`decorator`属性,可以自定义列的...