使用PrimeFaces开发数据导出实用程序
我的日常工作涉及大量使用數據。 我們使用關系數據庫來存儲所有內容,因為我們依賴于企業級的數據管理。 有時,具有將數據提取為簡單格式(例如電子表格)的功能很有用,以便我們可以按需進行操作。 這篇文章概述了我使用PrimeFaces 5.0生成有效且易于使用的基于JSF的數據導出實用程序所采取的步驟。 導出實用程序將生成一個電子表格,其中包括列標題。 用戶可以選擇要導出的數據庫字段以及應該以什么順序導出。
我們要確保我們擁有一個直觀的干凈用戶界面。 因此,我選擇不在屏幕上顯示任何數據。 而是,用戶界面包含一個PrimeFaces PickList組件,該組件列出了可供選擇的不同數據字段,以及一個用于生成導出的按鈕。 首先,設置數據庫基礎結構以使此導出實用程序成為可能。
對于這篇文章,我增強了AcmePools應用程序,該應用程序是通過我在OTN上發布的名為PrimeFaces in the Enterprise的文章開發的 。 導出實用程序允許將客戶數據導出到電子表格中。 客戶數據包含在NetBeans安裝在Apache Derby內的示例數據庫中,或者您可以將SQL腳本用于此文章。 在創建此導出實用程序之前,請在您的環境中下載或創建AcmePools項目。
數據導出實用程序分為兩部分,第一部分是PrimeFaces PickList組件,供用戶選擇要導出的字段,第二部分是導出按鈕,它將選擇的字段內容提取到電子表格中。 最終結果將類似于圖1所示的用戶界面。
圖1:數據導出實用程序
開發PickList組件
首先,創建數據基礎結構以支持PickList組件。 它由一個單獨的數據庫表組成,用于保存您要導出的實體數據的列名和標簽,以及一個可選的數據庫序列,用于填充該表的主鍵。 在這種情況下,數據庫表名為COLUMN_MODEL,我們用與CUSTOMER數據庫表的數據庫列名稱相對應的實體字段名稱填充該表。
-- Add support for data export create table column_model( id int primary key, column_name varchar(30), column_label varchar(150)); -- Optional sequence for primary key generation create sequence column_model_s start with 1 increment by 1; -- Load with field (database column) names insert into column_model values( 1, 'addressline1', 'Address Line 1');insert into column_model values( 2, 'addressline2', 'Address Line 2');insert into column_model values( 3, 'city', 'City');insert into column_model values( 4, 'creditLimit', 'Credit Limit');insert into column_model values( 5, 'customerId', 'Customer Id');insert into column_model values( 6, 'discountCode', 'Discount Code');insert into column_model values( 7, 'email', 'Email');insert into column_model values( 8, 'fax', 'Fax');insert into column_model values( 9, 'name', 'Name');insert into column_model values( 10, 'phone', 'Phone');insert into column_model values( 11, 'state', 'State');insert into column_model values( 12, 'zip', 'Zip');接下來,創建一個實體類,該實體類可用于從組件內部訪問列數據。 如果使用NetBeans等IDE,則可以通過向導輕松完成此操作。 如果使用NetBeans,請右鍵單擊com.acme.acmepools.entity包,然后選擇“新建”->“數據庫中的實體類”,然后為我們的示例數據庫選擇數據源。 當表列表填充時,選擇COLUMN_MODEL表,如圖2所示。最后,選擇“下一步”和“完成”以創建實體類。
圖2.數據庫中的NetBeans IDE新實體類
完成后,名為ColumnModel的實體類應如下所示:
接下來,為新生成的實體類創建EJB會話bean,以便組件可以查詢列數據。 您也可以根據需要使用IDE。 如果使用NetBeans,請右鍵單擊com.acme.acmepools.session包,然后選擇“新建”->“實體類的會話Bean”。 對話框打開后,從左側列表中選擇實體類“ com.acme.acmepools.entity.ColumnModel”,然后單擊“完成”(圖3)。
圖3:用于實體類的NetBeans IDE會話Bean對話框
創建會話bean之后,添加一個名為findId()的方法,該方法可用于根據指定的列名返回列ID值。 ColumnModelFacade的完整資源應如下所示:
接下來,創建一些幫助程序類,這些類將用于在PickList組件中加載和管理數據。 第一個類名為ColumnBean,它用于存儲實體數據,然后將其傳遞給PickList以供使用。 ColumnBean的代碼是一個簡單的POJO:
package com.acme.acmepools.bean;import java.math.BigDecimal;/**** @author juneau*/ public class ColumnBean {private BigDecimal id;private String columnName;private String columnLabel;public ColumnBean(BigDecimal id, String columnName, String columnLabel){this.id = id;this.columnName = columnName;this.columnLabel = columnLabel;}/*** @return the id*/public BigDecimal getId() {return id;}/*** @param id the id to set*/public void setId(BigDecimal id) {this.id = id;}/*** @return the columnName*/public String getColumnName() {return columnName;}/*** @param columnName the columnName to set*/public void setColumnName(String columnName) {this.columnName = columnName;}/*** @return the columnLabel*/public String getColumnLabel() {return columnLabel;}/*** @param columnLabel the columnLabel to set*/public void setColumnLabel(String columnLabel) {this.columnLabel = columnLabel;}}PickList組件需要使用PrimeFaces DualListModel來訪問和更新數據。 因此,我們必須實現一個類,該類可用于將實體數據強制到ColumnBean POJO中,然后將其存儲到DualListModel中,以便PickList組件可以利用它。 在下面的名為PickListBean的類中,構造函數接受作為實體數據的List <ColumnModel>作為參數,執行強制轉換,然后將其存儲到DualListModel <ColumnBean>集合中,以供組件使用。
package com.acme.acmepools.bean;/**** @author juneau*/import java.util.ArrayList; import java.util.List; import com.acme.acmepools.entity.ColumnModel;import org.primefaces.model.DualListModel;public class PickListBean {private DualListModel<ColumnBean> columns;private List<ColumnBean> source = null;private List<ColumnBean> target = null;public PickListBean(List<ColumnModel> columnModelList) {//Columns source = new ArrayList<ColumnBean>();target = new ArrayList<ColumnBean>();for(ColumnModel column:columnModelList){ColumnBean bean = new ColumnBean(column.getId(), column.getColumnName(), column.getColumnLabel());source.add(bean);}columns = new DualListModel<ColumnBean>(source, target);}public DualListModel<ColumnBean> getColumns() {return columns;}public void setColumns(DualListModel<ColumnBean> columns) {this.columns = columns;}}最后,我們需要創建一個控制器類來訪問所有這些數據。 為此,請在com.acme.acmepools.jsf包中創建一個名為ColumnModelController的類,并通過使用@Named和@SessionScoped對其進行注釋,使其成為CDI托管bean。 使該類實現Serializable。 初始控制器類應如下所示(我們稍后將對其進行更新以包括促進導出的方法):
@Named @SessionScoped public class ColumnModelController implements Serializable {@EJBColumnModelFacade ejbFacade;private PickListBean pickListBean;private List<ColumnModel> columns;public DualListModel<ColumnBean> getColumns() {pickListBean = new PickListBean(ejbFacade.findAll());return pickListBean.getColumns();}public void setColumns(DualListModel<ColumnBean> columns) {pickListBean.setColumns(columns);} }如您所見,getColumns()方法查詢ColumnModel實體,該實體通過PickListBean構造函數填充DualListModel <ColumnBean>。
這將處理數據庫基礎結構和業務邏輯……現在讓我們看一下用于PickList的PrimeFaces組件。 以下摘錄來自WebPages / poolCustomer / CustomerExport.xhtml視圖,其中包含PickList組件的標記:
<p:panel header="Choose Columns for Export"><p:picklist effect="bounce" itemlabel="#{column.columnLabel}" itemvalue="#{column.columnName}" showsourcecontrols="true" showtargetcontrols="true" value="#{columnModelController.columns}" var="column"><f:facet name="sourceCaption">Columns</f:facet><f:facet name="targetCaption">Selected</f:facet></p:picklist></p:panel>如您所見,PickList使用columnModelController.columns作為數據,然后使用columnLabel字段顯示要導出的實體字段的名稱。 源和目標PickList窗口的標題可通過構面進行自定義。 添加導出功能現在,我們已經開發了功能選擇列表,我們需要對選定的數據進行一些處理。 在本練習中,我們將使用PrimeFaces DataExporter組件提取數據并將其存儲到Excel電子表格中。 實際上,我們需要將DataTable合并到視圖中以首先顯示數據,然后可以使用DataExporter組件導出駐留在表中的數據。 為了構造將用于顯示數據的DataTable,我們需要向ColumnModelController類添加一些方法。 這些方法將使我們能夠動態地處理DataTable,以便我們可以根據在PickList中選擇的列構造列。 實際上,DataTable將查詢所有Customer數據,然后僅顯示在PickList中選擇的那些數據列。 (我們可以通過添加過濾器來修改此查詢,但這超出了本文的范圍)。 要向表中加載數據,我們只需調用com.acme.acmepools.jsf.CustomerController getItems()方法即可返回所有數據……public List <Customer> getItems(){if(items == null){items = getFacade()。findAll(); } 退換貨品; }…現在,我們將必要的方法添加到ColumnModelController,以便我們可以動態構造表。 首先,添加一個單擊“導出”按鈕將被調用的方法。 此方法將負責構建當前選擇的列列表:
public void preProcess(Object document) {System.out.println("starting preprocess");updateColumns();}接下來,讓我們看一下由preProcess()方法調用的updateColumns()的代碼:
/*** Called as preprocessor to export (after clicking Excel icon) to capture* the table component and call upon createDynamicColumns()*/public void updateColumns() {//reset table stateUIComponent table = FacesContext.getCurrentInstance().getViewRoot().findComponent(":customerExportForm:customerTable");table.setValueExpression("sortBy", null);//update columnscreateDynamicColumns();}updateColumns()方法將UIComponent綁定到JSF視圖中的表。 然后,它有能力提供排序(如果選擇)。 接下來,讓我們看一下被調用的createDynamicColumns()方法。
private void createDynamicColumns() {String[] columnKeys = this.getIncludedColumnsByName().split(",");columns = new ArrayList<>();for (String columnKey : columnKeys) {String key = columnKey.trim();columns.add(new ColumnModel(getColumnLabel(key), key));}}createDynamicColumns()方法可以完成一些工作。 首先,它從PickList中捕獲所有選定的列,并將它們存儲到名為columnKeys的String []中。 為此,我們使用名為getIncludedColumnsByName()的幫助程序方法,并以逗號分隔結果。 此方法的源如下,它基本上從PickListBean抓取當前選擇的列,并將每個列附加到String上,然后將其返回給調用方。
public String getIncludedColumnsByName() {String tempIncludedColString = null;System.out.println("Number of included columns:" + pickListBean.getColumns().getTarget().size());List localSource = pickListBean.getColumns().getTarget();for (int x = 0; x <= localSource.size() - 1; x++) {String tempModel = (String) localSource.get(x);if (tempIncludedColString == null) {tempIncludedColString = tempModel;} else {tempIncludedColString = tempIncludedColString + "," + tempModel;}}return tempIncludedColString;}接下來,createDynamicColumns()方法然后使用循環解析String []中的每個選定列,并將它們添加到columnList,后者將用于使用適當的列構造DataTable。
現在,讓我們看一下用于構造DataExport實用程序的標記:
<p:datatable id="customerTable" rendered="false" value="#{customerController.items}" var="item" widgetvar="customerTable"> <p:columns columnindexvar="colIndex" value="#{columnModelController.dynamicColumns}" var="column"><f:facet name="header"><h:outputtext value="#{column.header}"></h:outputtext></f:facet><h:outputtext value="#{item[column.property]}"></h:outputtext></p:columns></p:datatable><hr /> <h:outputtext value="Type of file to export: "><h:commandlink><p:graphicimage value="/faces/resources/images/excel.png"><p:dataexporter filename="customers" id="propertyXlsExport" preprocessor="#{columnModelController.preProcess}" target="customerTable" type="xls"></p:dataexporter></p:graphicimage></h:commandlink> </h:outputtext>如您所見,DataTable設置為不呈現,因為我們確實不希望顯示它。 相反,我們希望使用DataExporter組件導出其內容。 為了動態構造DataTable,這些列將調用columnModelController.dynamicColumns方法以返回動態列列表。 該方法如下所示:
public List<ColumnModel> getDynamicColumns() {return columns;}在DataExporter實用程序組件中,將columnModelController.preProcess方法分配給預處理器屬性以啟動動態列列表。 目標設置為customerTable小部件,該部件是我們根據所選列動態構建的DataTable。 為了將其導出到xls電子表格,必須在項目的Maven POM中添加org.apache.poi依賴項,如下所示:
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.7</version></dependency>就是這樣…現在您應該擁有使用PrimeFaces組件的功能齊全的數據導出實用程序。 使用以下鏈接可在GitHub上獲得完整的資源。 此代碼已用NetBeans IDE 8.0編寫,并已部署到GlassFish 4.0。 我在該項目中使用了PrimeFaces 5.0。
- GitHub來源: https : //github.com/juneau001/AcmePools
翻譯自: https://www.javacodegeeks.com/2014/12/developing-a-data-export-utility-with-primefaces.html
總結
以上是生活随笔為你收集整理的使用PrimeFaces开发数据导出实用程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 带有Swagger的Spring Res
- 下一篇: cdn可以预防ip被墙吗(cdn可以预防