PrimeFaces DataExporter仅导出首页数据,如何导出全部页数据?
解决PrimeFaces DataExporter仅导出当前页数据的问题
这个问题我之前也碰到过,PrimeFaces的DataExporter组件默认是基于当前页面的视图数据(也就是分页后的当前页)来导出的,要导出所有分页的数据,分以下几种情况处理:
方案一:直接使用exportAllPages属性(推荐,PrimeFaces 5.2+适用)
从PrimeFaces 5.2版本开始,DataExporter新增了exportAllPages属性,只需要把它设为true,就能直接导出所有符合过滤/排序条件的数据,无需额外的后台代码。
修改你的导出按钮代码即可:
<!-- 原导出按钮 --> <!-- <p:dataExporter type="xls" target="dataTable" fileName="current_page_data" /> --> <!-- 修改后的导出按钮 --> <p:dataExporter type="xls" target="dataTable" fileName="all_data" exportAllPages="true" />
这个属性会让组件绕过当前的分页设置,直接从数据源中获取所有匹配条件的记录进行导出,同时会保留你设置的过滤、排序规则,非常省心。
方案二:旧版本PrimeFaces(低于5.2)的自定义处理
如果你使用的是5.2之前的PrimeFaces版本,就需要通过后台Bean临时调整分页参数,导出完成后再恢复原有状态:
1. 后台Bean代码
import org.primefaces.component.datatable.DataTable; import javax.faces.context.FacesContext; import org.primefaces.PrimeFaces; @ManagedBean @ViewScoped public class YourBean { // 绑定页面的DataTable组件 @ManagedProperty("#{dataTable}") private DataTable dataTable; // 你的数据源 private List<YourEntity> items; // 导出全部数据的方法 public void exportAllData() { // 保存当前分页状态 int currentFirst = dataTable.getFirst(); int currentRows = dataTable.getRows(); // 设置DataTable显示所有数据(rows设为-1表示无分页限制) dataTable.setFirst(0); dataTable.setRows(-1); // 将原有分页状态存入Flash,方便导出后恢复 FacesContext.getCurrentInstance().getExternalContext().getFlash().put("restoreFirst", currentFirst); FacesContext.getCurrentInstance().getExternalContext().getFlash().put("restoreRows", currentRows); } // 恢复原有分页状态的方法 public void restorePagination() { Integer first = (Integer) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("restoreFirst"); Integer rows = (Integer) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("restoreRows"); if (first != null && rows != null) { dataTable.setFirst(first); dataTable.setRows(rows); // 刷新DataTable视图 PrimeFaces.current().ajax().update("dataTable"); } } // getter和setter方法 public DataTable getDataTable() { return dataTable; } public void setDataTable(DataTable dataTable) { this.dataTable = dataTable; } // ...其他getter/setter }
2. 前端页面代码
<!-- 绑定DataTable到后台Bean的变量 --> <p:dataTable id="dataTable" var="item" value="#{yourBean.items}" paginator="true" rows="10" binding="#{yourBean.dataTable}"> <!-- 你的列定义 --> </p:dataTable> <!-- 触发导出的按钮 --> <p:commandButton value="导出全部数据" action="#{yourBean.exportAllData}" oncomplete="PF('exporterWidget').export()" update="dataTable" /> <!-- 隐藏的DataExporter,通过widgetVar触发导出 --> <p:dataExporter widgetVar="exporterWidget" type="xls" target="dataTable" fileName="all_data" /> <!-- 页面加载时恢复分页状态 --> <f:event type="postAddToView" listener="#{yourBean.restorePagination}" />
方案三:使用LazyDataModel时的额外处理
如果你的DataTable使用了LazyDataModel做懒加载,除了上述方案外,还需要确保LazyDataModel的load方法能正确处理rows=-1的情况,返回所有数据:
public class YourLazyModel extends LazyDataModel<YourEntity> { @Override public List<YourEntity> load(int first, int rows, String sortField, SortOrder sortOrder, Map<String, Object> filters) { List<YourEntity> data; if (rows == -1) { // 查询所有符合过滤条件的数据 data = yourService.getAllData(filters); // 设置总记录数 this.setRowCount(data.size()); } else { // 正常分页查询 data = yourService.getPagedData(first, rows, sortField, sortOrder, filters); this.setRowCount(yourService.getTotalCount(filters)); } return data; } }
这样当DataExporter触发导出时,LazyModel会返回所有数据,而不是分页后的子集。
内容的提问来源于stack exchange,提问作者user1930634
相关产品推荐
相关产品推荐

