primefaces_使用PrimeFaces开发数据导出实用程序

primefaces

我的日常工作涉及大量使用数据。 我们使用关系数据库来存储所有内容,因为我们依赖于企业级的数据管理。 有时,具有将数据提取为简单格式(例如电子表格)的功能很有用,以便我们可以按需进行操作。 这篇文章概述了我使用PrimeFaces 5.0生成有效且易于使用的基于JSF的数据导出实用程序所采取的步骤。 导出实用程序将生成一个电子表格,其中包括列标题。 用户可以选择要导出的数据库字段以及应该以什么顺序导出。

我们要确保我们拥有一个直观的干净用户界面。 因此,我选择不在屏幕上显示任何数据。 而是,用户界面包含一个PrimeFaces PickList组件,该组件列出了可供选择的不同数据字段,以及一个用于生成导出的按钮。 首先,设置数据库基础结构以使此导出实用程序成为可能。

对于这篇文章,我增强了AcmePools应用程序,该应用程序是通过我在OTN上发布的名为PrimeFaces in the Enterprise的文章开发的 。 导出实用程序允许将客户数据导出到电子表格中。 客户数据包含在NetBeans在Apache Derby中安装的示例数据库中,或者您可以在此文章中使用SQL脚本。 在创建此导出实用程序之前,请在您的环境中下载或创建AcmePools项目。

数据导出实用程序分为两部分,第一部分是PrimeFaces PickList组件,供用户选择要导出的字段,第二部分是导出按钮,它将选择的字段内容提取到电子表格中。 最终结果将类似于图1所示的用户界面。

图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新实体类

图2.来自数据库的NetBeans IDE新实体类


完成后,名为ColumnModel的实体类应如下所示:

package com.acme.acmepools.entity;import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;/**** @author Juneau*/
@Entity
@Table(name = "COLUMN_MODEL")
@XmlRootElement
@NamedQueries({@NamedQuery(name = "ColumnModel.findAll", query = "SELECT c FROM ColumnModel c"),@NamedQuery(name = "ColumnModel.findById", query = "SELECT c FROM ColumnModel c WHERE c.id = :id"),@NamedQuery(name = "ColumnModel.findByColumnName", query = "SELECT c FROM ColumnModel c WHERE c.columnName = :columnName"),@NamedQuery(name = "ColumnModel.findByColumnLabel", query = "SELECT c FROM ColumnModel c WHERE c.columnLabel = :columnLabel")})
public class ColumnModel implements Serializable {private static final long serialVersionUID = 1L;@Id@Basic(optional = false)@NotNull@Column(name = "ID")private BigDecimal id;@Size(max = 30)@Column(name = "COLUMN_NAME")private String columnName;@Size(max = 150)@Column(name = "COLUMN_LABEL")private String columnLabel;public ColumnModel() {}public ColumnModel(BigDecimal id) {this.id = id;}public BigDecimal getId() {return id;}public void setId(BigDecimal id) {this.id = id;}public String getColumnName() {return columnName;}public void setColumnName(String columnName) {this.columnName = columnName;}public String getColumnLabel() {return columnLabel;}public void setColumnLabel(String columnLabel) {this.columnLabel = columnLabel;}@Overridepublic int hashCode() {int hash = 0;hash += (id != null ? id.hashCode() : 0);return hash;}@Overridepublic boolean equals(Object object) {// TODO: Warning - this method won't work in the case the id fields are not setif (!(object instanceof ColumnModel)) {return false;}ColumnModel other = (ColumnModel) object;if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {return false;}return true;}@Overridepublic String toString() {return "com.acme.acmepools.entity.ColumnModel[ id=" + id + " ]";}}

接下来,为新生成的实体类创建一个EJB会话bean,以便组件可以查询列数据。 您也可以根据需要使用IDE。 如果使用NetBeans,请右键单击com.acme.acmepools.session包,然后选择“新建”->“实体类的会话Bean”。 对话框打开后,从左侧列表中选择实体类“ com.acme.acmepools.entity.ColumnModel”,然后单击“完成”(图3)。

图3:用于实体类的NetBeans IDE会话Bean对话框

图3:用于实体类的NetBeans IDE会话Bean对话框


创建会话bean之后,添加一个名为findId()的方法,该方法可用于根据指定的列名返回列ID值。 ColumnModelFacade的完整资源应如下所示:

package com.acme.acmepools.session;import com.acme.acmepools.entity.ColumnModel;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;/**** @author Juneau*/
@Stateless
public class ColumnModelFacade extends AbstractFacade {@PersistenceContext(unitName = "com.acme_AcmePools_war_AcmePools-1.0-SNAPSHOTPU")private EntityManager em;@Overrideprotected EntityManager getEntityManager() {return em;}public ColumnModelFacade() {super(ColumnModel.class);}public ColumnModel findId(String columnName){return (ColumnModel) em.createQuery("select object(o) from ColumnModel as o " +"where o.columnName = :columnName").setParameter("columnName", columnName).getSingleResult();}}

接下来,创建一些帮助程序类,这些类将用于在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何优雅地实现判断一个值是否在一个集合中?

如何判断某变量是否在某个集合中&#xff1f;注意&#xff0c;这里的集合可能并不是指确定的常量&#xff0c;也可能是变量。版本0#include int main(){int a 5;if(a 1 || a 2 || a 3 || a 4 || a 5){std::cout<<"find it"<<std::endl;}return 0;…

骚操作:利用强弱符号制作插件库

当有强符号和弱符号时&#xff0c;选择使用强符号那么我们正可以利用这个原则做以下事情&#xff1a;定义为弱符号&#xff0c;如果是弱符号&#xff0c;使用默认行为如果链接了库&#xff0c;是强符号&#xff0c;则使用外部定义行为以此来实现一个类似插件的功能。通俗一点说…

c语言里 t是什么作用,c语言里的\t是什么意思

c语言里的&#xff3c;t是什么意思以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;c语言里的&#xff3c;t是什么意思正宗叫法是“水平制表符”&#xff0c;就是在输出媒体上水平跳过多个空格…

函数或全局变量重复定义时会怎样?

可能有些朋友第一反应是&#xff0c;那肯定是编译不过喽&#xff1a;// fun.c #include void func() {printf("编程珠玑\n"); }// main.c #include void func() {printf("公众号\n"); } int main(void) {func();return 0; }编译&#xff1a;$ gcc -o main …

当C语言函数执行成功时,返回1和返回0究竟哪个好?

基本上&#xff0c;没有人会将大段的C语言代码全部塞入 main() 函数。更好的做法是按照复用率高&#xff0c;耦合性低的原则&#xff0c;尽可能的将代码拆分不同的功能模块&#xff0c;并封装成函数。C语言代码的组合千变万化&#xff0c;因此函数的功能可能会比较复杂&#xf…

ubuntu自定义安装里怎么选_超市里的五香粉怎么选?看懂配料表,两个小技巧,不怕选不好。...

点击右上角【关注】&#xff0c;可获得本头条号推荐的更多美食干货五香粉是家庭常用的一种调味料&#xff0c;焖、炖、烧、煮、卤都常备使用&#xff0c;如今市场上的五香粉品牌也是相当繁多&#xff0c;质量也是参差不齐&#xff0c;有时买到的五香粉烧制的菜肴根本就不好吃&a…

原来C语言还可以这样实现“泛型编程”!

在回答标题问题之前&#xff0c;先了解下什么是泛型编程。泛型编程&#xff08;generic programming&#xff09;是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型&#xff0c;在实例化时作为参数指明这些类型。C支持…

javadoc 标签_新的Javadoc标签@ apiNote,@ implSpec和@implNote

javadoc 标签如果您已经在使用Java 8&#xff0c;则可能会看到一些新的Javadoc标签&#xff1a; apiNote &#xff0c; implSpec和implNote 。 他们怎么了&#xff1f; 如果要使用它们&#xff0c;该怎么办&#xff1f; 总览 该帖子将快速查看标签的来源和当前状态。 然后&…

C语言入门基础之输入和输出

标准输入函数在stdio.h中scanf声明如下&#xff1a;/* Read formatted input from stdin.This function is a possible cancellation point and therefore notmarked with __THROW. */ extern int scanf (const char *__restrict __format, ...) __wur;使用Mac或Linux的同学&am…

camel java_与Java EE和Camel的轻量级集成

camel javaEnterprise Java具有不同的风格和观点。 从简单的平台技术&#xff08;众所周知的Java EE&#xff09;开始&#xff0c;到不同的框架和集成方面&#xff0c;最后是涉及以数据为中心的用户界面或特定可视化效果的用例。 Java EE本身无法解决的最突出的问题是“集成”。…

c语言 伪随机数程序,C语言的伪随机数

一直想好好的系统的学习一下C语言的伪随机数&#xff0c;今天终于逮到机会了伪随机数C语言中有可以产生随机数据的函数&#xff0c;需要添加stdlib.h和time.h头文件。首先在main函数开头加上srand(unsigned)time(NULL))。先来介绍一下srand头文件&#xff1a;定义函数&#xff…

最大隶属度原则_模糊数学笔记:六、模糊模型识别-I(最大隶属度原则)

1、模型识别的问题提出模型识别&#xff0c;通俗地理解即是对一个类别未知的对象进行归类&#xff08;或者叫分类&#xff09;。这里与聚类不同的是&#xff0c;聚类实际上是要区分出已有的样本哪些属于同一类&#xff0c;但并没有参考标准。而识别则事先有参考的标准&#xff…

C语言经典题

C 库函数 - tanh()描述C 库函数 double tanh(double x) 返回 x 的双曲正切。声明下面是 tanh() 函数的声明。double tanh(double x)参数x -- 浮点值。返回值该函数返回 x 的双曲正切。实例下面的实例演示了 tanh() 函数的用法。#include#include int main (){ double x, ret;…

C++11的模板改进

C11关于模板有一些细节的改进&#xff1a;模板的右尖括号模板的别名函数模板的默认模板参数模板的右尖括号C11之前是不允许两个右尖括号出现的&#xff0c;会被认为是右移操作符&#xff0c;所以需要中间加个空格进行分割&#xff0c;避免发生编译错误。int main() {std::vecto…

android 第三方圆弧进度条,android 可配置的圆弧进度条

Arc ProgressBar Configurable 圆弧环形进度条DEMOAttributesnameformatdescriptionborderWidthinteger圆弧边框的宽度progressStyletick/arc进度条类型&#xff0c;tick 为带刻度的radiusinteger半径arcbgColorcolor圆弧的边框背景degreeinteger弧度&#xff0c;设置为 0 即为…

C++定时器的实现之格式修订版

个人认为一个完备的定时器需要有如下功能&#xff1a;在某一时间点执行某一任务在某段时间后执行某一任务重复执行某一任务N次&#xff0c;任务间隔时间T那么如何实现定时器呢&#xff1f;下面是我自己实现的定时器逻辑&#xff0c;源码链接最后会附上。定时器中主要的数据结构…

java 性能调优_Java性能调优调查结果(第四部分)

java 性能调优这是本系列中的最后一篇文章&#xff0c;我们将分析我们在2014年10月进行的Java Performance Tuning Survey的结果。如果您尚未阅读第一篇文章&#xff0c;建议您首先阅读以下内容&#xff1a; 性能问题的频率和严重性 最受欢迎的监控解决方案 查找根本原因的工…

Android接入热敏打印机,Android 关于佳博和汉印蓝牙热敏打印机开发

接上篇文章Android之BLE(低功耗)蓝牙开发&#xff0c;本篇文章针对上篇博文中提出的两款打印机的开发流程进行记录。首先不管时佳博打印机还是汉印打印机&#xff0c;都是先对他们各自的lib进行导入&#xff0c;如图&#xff1a;导入lib之后&#xff0c;一定要记得进行sync pro…

C 桥接模式 - 开关和电器

桥接模式&#xff08;Bridge Pattern&#xff09;是将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。1模式结构UML 结构图&#xff1a;Abstraction&#xff08;抽象类&#xff09;&#xff1a;用于定义抽象类的接口&#xff0c;并且维护一个指向 Implementor…

javafx显示image_如何摆脱JavaFX中的重点突出显示

javafx显示image今天&#xff0c;有人问我是否知道摆脱JavaFX控件&#xff08;分别是按钮&#xff09;的焦点突出的方法&#xff1a; 有关此问题的大多数文章和提示建议添加&#xff1a; .button:focused {-fx-focus-color: transparent; }但是使用这种样式&#xff0c;仍然…