primefaces4.0基本教程以及增刪改查


    最近試着用了用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的心得與體會,還不算太成熟,希望能與大家多多交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM