最近试着用了用primefaces4.0,准备写一个基本的增删改查以及分页程序,但在写的过程中发现了很多问题,本想通过百度、谷歌解决,但无奈中文资料非常少,笔者在坑中不停的打滚,终于完成了一个有着基本功能的,还能看的过去的demo,想和大家一起分享一下,并希望能帮上和我一样陷入primefaces坑中的人。代码是仓促完成的,难免会有些缺点,还希望大家多多交流。http://www.mkyong.com/tutorials/jsf-2-0-tutorials/这个网站给了我非常大的帮助,在此表示严重感谢。

先来介绍一下primefaces吧,谈到primefaces,就要说到jsf了,jsf全称java server faces,简单来说就是一个Web 应用程序的新标准 Java 框架,而primeaces就是其中的一个实现,界面还是非常华丽的(笔者的意思是不大需要美工了),让笔者立刻想到了ExtJs...

接下来进入正题,先说说primefaces的基本环境配置

一、环境配置

    先到官方网站https://javaserverfaces.java.net/下载2.2.4版的jsf ,primefaces是基于它的,然后去http://www.primefaces.org/downloads.html下载primefaces-4.0.jar,还需要jstl.jar和standard.jar包,最后加上类似数据库连接等别的jar包,lib目录下就完成了。

再看web.xml,需要加入以下代码:

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
</servlet-mapping>

然后编写一个传统的helloworld程序来测试环境是否配置成功

show.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
    </h:head>
    <p:editor value=“hello world” />
</html>

打开浏览器,输入http://localhost:<端口号>/<项目名称>/faces/show.xhtml,如果看到如下结果,说明基本环境已经部署成功。


    这里要注意个问题,就是<h:head></h:head>一定要加上,否则primefaces不会渲染它,笔者曾被这个坑稍微折磨了那么一会。。

二、分页查询

    假设有如下实体类

PublicInfo.java

package test.entity;

import java.io.Serializable;
import java.util.Date;

public class Info implements Serializable
{
    private Integer id;
    private String title;
    private Date time;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }
}

在数据库中有一个与之对应的表,字段分别是id(number),title(varchar),time(date),这三个字段类型可以代表绝大多数情况。这里要注意,实体类要实现Serializable接口,否则可能会出现一些小问题。这里顺便说一下吧,因为jsf框架的设计导致了前台与后台的联系十分密切,所以,需要与前台交互的类一般都要实现Serializable接口。

primefaces内提供了一个类LazyDataModel,只要继承这个类,并实现它的三个方法,我们的后台分页就已经完成一半了,代码如下:

LazyInfoDataModel.java

package test.bean;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import test.entity.Info;

public class LazyInfoDataModel extends LazyDataModel<Info>
{
    private List<Info> list;

    public LazyInfoDataModel(){}

    @Override
    public List<Info> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters)
    {
        //这个方法不光可以实现分页,也可以实现过滤与排序
        /*我们暂时只实现简单的分页,
           first代表起始位置,pageSize代表查询数量,其他参数可以暂时不管,这两个参数就可以实现分页功能
           要查询出数据与数量
        */
        //setRowCount(数量); //这个方法一定要执行!

        //list = 查询结果
        return list;
    }

    @Override
    public Info getRowData(String rowKey)
    {
        for(Info info : list)
        {
            if(info.getId().toString().equals(rowKey))
            {
                return info;
            }
        }  

        return null;
    }  

    @Override
    public Object getRowKey(Info info)
    {
        return info.getId();
    }
}

后台还需要最后一部分,这一部分是与前台密切相关的,这个类主要负责与前台进行数据的交互,以及实现一些业务逻辑,代码如下:

InfoBean.java

package test.bean;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.model.LazyDataModel;
import test.entity.Info;

@ManagedBean(name="infoBean")
@SessionScoped
public class InfoBean implements Serializable
{
    private LazyDataModel<Info> lazyModel = new LazyInfoDataModel();

    public LazyDataModel<Info> getLazyModel() {
        return lazyModel;
    }

    public void setLazyModel(LazyDataModel<Info> lazyModel) {
        this.lazyModel = lazyModel;
    }
}

这里还是要说明一下,@ManagedBean(name="infoBean")这个是jsf2的新特性,在jsf1中,需要写一个xml配置文件来配置,但jsf2取消了xml配置文件,改为使用注解。其中的name属性指定的值是在前台页面中这个类的别名,一会大家可以在前台页面的代码中看到。@SessionScoped表示作用域,其他的作用域还有@RequestScoped、@ViewScoped,看看名字大家就知道是怎么回事了,本教程的业务逻辑需要session作用域,所以就使用@SessionScoped了。

最后是前台部分了,直接上代码:

show.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
    </h:head>
    <h:form id="form1">
        <p:dataTable var="info" value="#{infoBean.lazyModel}" paginator="true" rows="10" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15" id="infoTable" lazy="true">
            <p:column headerText="id">
                <h:outputText value="#{info.id}" />
            </p:column>

            <p:column headerText="title">
                <h:outputText value="#{info.title}" />
            </p:column>

            <p:column headerText="time">
                <h:outputText value="#{info.time}">
                    <f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" />
                </h:outputText>
            </p:column>
        </p:dataTable>
    </h:form>
</html>

又要做一些说明了,大家注意看这个value="#{infoBean.lazyModel}",其中的infobean就是前面InfoBean的@ManagedBean(name="infoBean")中的属性,var="info",这个大家应该一看就知道了。还有时间处理<f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" /> ,也要注意一下,然后就可以看看页面效果了。

以上就是分页查询的基本代码(好吧,测试数据是挺坑爹的...),大家可以看到,primefaces已经帮我们实现了分页,还可以指定每页显示的条数,大家快试试吧。

大家还可以参考官方的例子http://www.primefaces.org/showcase/ui/datatableLazy.jsf,在官方的例子中,还提供了过滤与排序的demo。

   

三、添加

    我们准备添加一个add按钮,弹出一个输入框,让用户输入要添加的信息,保存后刷新页面。

先上修改后的前台页面代码:

show.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
    </h:head>
    <h:form id="form1">
        <p:dataTable var="info" value="#{infoBean.lazyModel}" paginator="true" rows="10" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15" id="infoTable" lazy="true">
            <p:column headerText="id">
                <h:outputText value="#{info.id}" />
            </p:column>

            <p:column headerText="title">
                <h:outputText value="#{info.title}" />
            </p:column>

            <p:column headerText="time">
                <h:outputText value="#{info.time}">
                    <f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" />
                </h:outputText>
            </p:column>
        </p:dataTable>
    </h:form>   

    <p:commandButton value="add" onclick="PF('addDialog').show()" />

    <p:dialog header="add" widgetVar="addDialog" modal="true">
        <h:form id="form3">
            <h:panelGrid columns="2" cellpadding="5" id="addPanel">
                <p:outputLabel value="id" />
                <p:inputText value="#{infoBean.selected.id}" />

                <p:outputLabel value="title" />
                <p:inputText value="#{infoBean.selected.title}" />

                <p:outputLabel value="time" />
                <p:inputMask value="#{infoBean.selected.time}" mask="9999-99-99 99:99:99">
                    <f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" />
                </p:inputMask>

                <p:commandButton value="confirm" oncomplete="PF('addDialog').hide()" actionListener="#{infoBean.add}" update=":form1:infoTable,form3"  />
            </h:panelGrid>
        </h:form>
    </p:dialog>
</html>

又到了说明的时间了,与之前的show.xhtml相比,我们增加了一个<p:commandButton />和一个<p:dialog />,注意一下这里<p:inputMask value="#{infoBean.selected.time}" mask="9999-99-99 99:99:99">,我们使用了一个<p:inputMask />标签,这个标签可以限制用户的输入格式,这样转成date就更加方便了。还有一点需要注意,我们用了一个id为form3的<h:form />标签将需要提交的信息包在里面,一定要加上这个form,否则会有一些不大好解释的问题,笔者之前又被这个问题小折磨了会。。还要注意actionListener="#{infoBean.add}"和update=":form1:infoTable,form3",通过actionListener可以看到jsf中前台与后台是如何进行交互的,update表示执行完这个表单提交需要更新的地方,我们要更新查询页面,也要更新自己的form3,否则当用户再想增加新内容时,看到已经填好了信息,他会不会迷惑呢。。。

再是后台代码:

InfoBean.java

package test.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import org.primefaces.model.LazyDataModel;import test.entity.Info;

@ManagedBean(name="infoBean")
@SessionScoped
public class InfoBean implements Serializable
{
    private LazyDataModel<Info> lazyModel = new LazyInfoDataModel();
    private Info selected = new Info();

    public void add(ActionEvent e)
    {
//在这里写上向数据库保存的内容的代码,selected就是前台传来的待保存信息

        selected = new Info(); //由于是session作用域,会存在脏数据的问题,我们清除它
    }

    public LazyDataModel<Info> getLazyModel() {
        return lazyModel;
    }

    public void setLazyModel(LazyDataModel<Info> lazyModel) {
        this.lazyModel = lazyModel;
    }

    public Info getSelected() {
        return selected;
    }

    public void setSelected(Info selected) {
        this.selected = selected;
    }
}

我们增加了一个selected和一个add方法,具体的对应关系和前台的参照一下

然后是效果图:

我们添加一个id为2的数据,提交

可以看到,id为2的那条数据已经添加进去了。

四、更新&删除

    前台代码:

show.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
    <h:head>
    </h:head>
    <h:form id="form1">
        <p:dataTable var="info" value="#{infoBean.lazyModel}" paginator="true" rows="10" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15" id="infoTable" lazy="true">
            <p:column headerText="id">
                <h:outputText value="#{info.id}" />
            </p:column>

            <p:column headerText="title">
                <h:outputText value="#{info.title}" />
            </p:column>

            <p:column headerText="time">
                <h:outputText value="#{info.time}">
                    <f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" />
                </h:outputText>
            </p:column>

            <p:column headerText="">
                <p:commandButton value="delete">
                    <p:ajax event="click" listener="#{infoBean.select(info)}" oncomplete="PF('delDialog').show()" />
                </p:commandButton>
                <p:commandButton value="update">
                    <p:ajax event="click" listener="#{infoBean.select(info)}" oncomplete="PF('updateDialog').show()" update=":form4" />
                </p:commandButton>
            </p:column>
        </p:dataTable>
    </h:form>    

    <p:dialog header="Are you sure?" widgetVar="delDialog" modal="true">
        <h:form id="form2">
            <h:panelGrid columns="2" cellpadding="5" id="addPanel">
                <f:facet name="facet1">
                    <p:outputLabel value="Are you sure?" />
                </f:facet>

                <p:commandButton value="yes" actionListener="#{infoBean.delete}" update=":form1:infoTable" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" oncomplete="PF('delDialog').hide()" />
                <p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" oncomplete="PF('delDialog').hide()" />
            </h:panelGrid>
        </h:form>
    </p:dialog>

    <p:commandButton value="add" onclick="PF('addDialog').show()" />

    <p:dialog header="add" widgetVar="addDialog" modal="true">
        <h:form id="form3">
            <h:panelGrid columns="2" cellpadding="5" id="addPanel">
                <p:outputLabel value="id" />
                <p:inputText value="#{infoBean.selected.id}" />

                <p:outputLabel value="title" />
                <p:inputText value="#{infoBean.selected.title}" />

                <p:outputLabel value="time" />
                <p:inputMask value="#{infoBean.selected.time}" mask="9999-99-99 99:99:99">
                    <f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" />
                </p:inputMask>

                <p:commandButton value="confirm" oncomplete="PF('addDialog').hide()" actionListener="#{infoBean.add}" update=":form1:infoTable,form3"  />
            </h:panelGrid>
        </h:form>
    </p:dialog>

    <p:dialog header="update" widgetVar="updateDialog" modal="true">
        <h:form id="form4">
            <h:panelGrid columns="2" cellpadding="5" id="addPanel">
                <p:outputLabel value="id" />
                <p:inputText value="#{infoBean.selected.id}" readonly="true" />

                <p:outputLabel value="title" />
                <p:inputText value="#{infoBean.selected.title}" />

                <p:outputLabel value="time" />
                <p:inputMask value="#{infoBean.selected.time}" mask="9999-99-99 99:99:99">
                    <f:convertDateTime timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" locale="zh" />
                </p:inputMask>

                <p:commandButton value="confirm" oncomplete="PF('updateDialog').hide()" actionListener="#{infoBean.update}" update=":form1:infoTable"  />
            </h:panelGrid>
        </h:form>
    </p:dialog>
</html>

注意一下这里<p:ajax event="click" listener="#{infoBean.select(info)}" oncomplete="PF('updateDialog').show()" update=":form4" />,这里是笔者在做这个项目的过程中遇到的最头疼的问题,这里涉及到一个传值的问题,原来笔者是这么写的<p:commandButton actionListener="#{infoBean.select(info)}" oncomplete="PF('updateDialog').show()" />,而且primefaces官方demo也是这么写,但笔者在测试时发现,这样写会先调用oncomplete,显示dialog,然后再调用actionListener,在dialog显示的时候后台还没有接受到值,所以会报错,估计是笔者运气好吧,想到了一个这样的方法,可以解决这个问题。

后台代码

InfoBean.java

package test.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import org.primefaces.model.LazyDataModel;import test.entity.Info;

@ManagedBean(name="infoBean")
@SessionScoped
public class InfoBean implements Serializable
{
    private LazyDataModel<Info> lazyModel = new LazyInfoDataModel();
    private Info selected = new Info();

    public void select(Info selected)
    {
        this.selected = selected;
    }

    public void add(ActionEvent e)
    {
        //jdbc

        selected = new Info();
    }

    public void update(ActionEvent e)
    {
        //jdbc

        selected = new Info();
    }

    public void delete(ActionEvent e)
    {
        //jdbc

        selected = new Info();
    }

    public LazyDataModel<Info> getLazyModel() {
        return lazyModel;
    }

    public void setLazyModel(LazyDataModel<Info> lazyModel) {
        this.lazyModel = lazyModel;
    }

    public Info getSelected() {
        return selected;
    }

    public void setSelected(Info selected) {
        this.selected = selected;
    }
}

primefaces4.0基本教程以及增删改查的更多相关文章

  1. Yii2.0高级框架数据库增删改查的一些操作(转)

    yii2.0框架是PHP开发的一个比较高效率的框架,集合了作者的大量心血,下面通过用户为例给大家详解yii2.0高级框架数据库增删改查的一些操作 --------------------------- ...

  2. Yii2.0高级框架数据库增删改查的一些操作

    yii2.0框架是PHP开发的一个比较高效率的框架,集合了作者的大量心血,下面通过用户为例给大家详解yii2.0高级框架数据库增删改查的一些操作 --------------------------- ...

  3. Asp.Net WebApi学习教程之增删改查

    webapi简介 在asp.net中,创建一个HTTP服务,有很多方案,以前用ashx,一般处理程序(HttpHandler),现在可以用webapi 微软的web api是在vs2012上的mvc4 ...

  4. java springboot整合zookeeper入门教程(增删改查)

    java springboot整合zookeeper增删改查入门教程 zookeeper的安装与集群搭建参考:https://www.cnblogs.com/zwcry/p/10272506.html ...

  5. [py]flask从0到1-模板/增删改查

    flask知识点 1.后端渲染html到前端 render_template 2.后端获取前端数据 request.args.get 3.前端获取后端数据 模板 4.警示消息 flash {{ get ...

  6. NetCore2.0 RozarPage自动生成增删改查

    原文链接:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/web-api-help-pages-using-swagger 上面的只是原文 ...

  7. SQLite 入门教程(四)增删改查,有讲究 (转)

    转于: SQLite 入门教程(四)增删改查,有讲究 一.插入数据 INSERT INTO 表(列...) VALUES(值...) 根据前面几篇的内容,我们可以很轻送的创建一个数据表,并向其中插入一 ...

  8. SSH(Struts 2.3.31 + Spring 4.1.6 + Hibernate 5.0.12 + Ajax)框架整合实现简单的增删改查(包含分页,Ajax 无刷新验证该用户是否存在)

    软件152 余建强 该文将以员工.部门两表带领大家进入SSH的整合教程: 源码下载:http://download.csdn.net/detail/qq_35318576/9877235 SSH 整合 ...

  9. 微软Connect教程系列--自动生成增删改查页面工具介绍(二)

    本章课程描述了vs2015的三个特点,其中主要将描述在vs2015下面,使用命令自动生成增删改查界面,具体如下: 1.web.config文件不在存在,用config.json替代,以适应支撑vs的插 ...

随机推荐

  1. C++之再续前缘(二)——类和对象(上)

    1.类的构成:数据和函数 public:可以由在类外由类的对象访问 private:只能由类内的成员函数访问 protected:可以由本类的成员函数访问,也可以由本类的派生类的成员函数访问 访问权限 ...

  2. BIEE报表开发

    (1)报表开发实例结果图 (2)开发报表步骤: (1)创建分析 (2)创建仪表盘提示 (3)创建仪表盘并发布 登录网址,输入用户名和密码 1) 新建——>分析——>选择主题区域——> ...

  3. springMVC的@ResponseBody、@RequestBody使用需要注意的地方

    springMVC我觉得比struts2好的其中一个原因就是可以使用注解解析json数据,方便快捷.但是,即使如此,还是有需要注意的地方. 1.返回的地方设置@ResponseBody,请求的对象参数 ...

  4. css-css权威指南学习笔记3

    第三章 结构和层叠 1.确定应向一个元素应用哪些值时,用户代理不仅要考虑继承,还要考虑声明的特殊性,另外需要考虑声明本身的来源,这个过程就称为层叠.. 2.特殊性.如果一个元素有两个或多个冲突的属性声 ...

  5. 【poj1741】 Tree

    http://poj.org/problem?id=1741 (题目链接) 题意 给出一个n个节点的带权树,求树上距离不超过K的所有点对的个数. solution  点分治裸题.所谓的点分治,就是对于 ...

  6. 推荐一个学习golang的地址

    链接打开后,文字可以点击! http://yougg.github.io/static/gonote/GolangStudy.html#

  7. 关于PHP代码审计和漏洞挖掘的一点思考

    这里对PHP的代码审计和漏洞挖掘的思路做一下总结,都是个人观点,有不对的地方请多多指出. PHP的漏洞有很大一部分是来自于程序员本身的经验不足,当然和服务器的配置有关,但那属于系统安全范畴了,我不太懂 ...

  8. Linux 开机 logo 修改

    从内核被解压到文件系统被挂载,我们看到的经典画面是一个小企鹅.如果嫌小企鹅枯燥,我们可以把它换掉. 1. 准备图片 这里需要的是 ppm 图片,所以,我们需要把常见格式给转换为 .ppm 才能使用.c ...

  9. Beta版本——第二次冲刺博客

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  10. BCE0019: '' is not a member of 'UnityEngine.Component'的问题

    看自学网上的Unity3D的视频,其中视频中的实力代码: n.rigidbody.AddForce(fwd * 28000); 这个代码运行会出现错误: BCE0144: 'UnityEngine.C ...