最近试着用了用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. android开发之生命周期

    android开发之生命周期 一:Activity的生命周期: 这几天了了解了安卓Activity的生命周期,对于生命周期有了大概的理解: 一个Activity的生命周期也就是Activity从生成到 ...

  2. 内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例

    内部类访问外部类的变量必须是final吗? 如下: package com.java.concurrent; class A { int i = 3; public void shout() { cl ...

  3. UOJ244 【UER #7】短路

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  4. OrCAD Capture使用记录

    1.安装 ①修改host_ID为主机名称(如果填不对,安装过程会提示你再填一次):其后跟的是机子的MAC地址,用ipconfig /all 可以查看. ②下一行的FLEMlm,后面跟的是文件cdslm ...

  5. 让AutoMapper更好用

    AutoMapper Dto与EF实体之间的转换用AutoMapper会变的很方便.很高效,是大多数项目的选择.博主本人的项目也在使用AutoMapper这个组件 好用归好用,但是想要把它用好又是另一 ...

  6. Linux Command Line Basics

    Most of this note comes from the Beginning the Linux Command Line, Second Edition by Sander van Vugt ...

  7. HDU 3530 Subsequence(单调队列)

    传送门 Description There is a sequence of integers. Your task is to find the longest subsequence that s ...

  8. Java 线程池的使用

    转载原文链接: http://www.cnblogs.com/dolphin0520/p/3932921.html 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有 ...

  9. easyUI validatebox设置值和获取值,以及属性和方法

    一:表单元素使用easyui时,textbox和validatebox设置值和获取值的方式不一样[转] 1.为text-box设置值只能使用id选择器选择表单元素,只能使用textbox(" ...

  10. vm centos 添加网卡 无配置文件

    vm centos 添加网卡 无配置文件 解决办法 [root@test ~]# ifconfig eth0 Link encap:Ethernet HWaddr 00:0C:29:C8:41:FB ...