1. 程式人生 > >JSF框架整理(一)

JSF框架整理(一)

一、框架簡介

        JavaServer Faces (JSF) 是一種用於構建Java Web 應用程式的標準框架,它提供了一種以元件為中心的使用者介面(UI)構建方法,從而簡化了Java伺服器端應用程式的開發。

典型的JSF應用程式包含下列部分:

  • 一組JSP頁面

  • 一組後臺bean(為在一個頁面上的UI元件定義的屬性和函式的JavaBean元件)

  • 應用程式配置資原始檔(定義頁面導航規則、配置bean和其它的自定物件,如自定義元件)

  • 部署描述檔案(web.xml)

  • 一組由應用程式開發者建立的自定義物件(有可能)

  • 一些可能包含自定義元件、約束、轉換器或者監聽器的物件

  • 為在頁面中表現自定義物件的一組自定義tag

包含JSP頁面的JSF應用程式也使用由為了表現UI元件和在頁面上的其他物件的JSF技術而定義的標準的tag庫。

二、JSF生命週期

JSF(JavaServer Faces)應用程式框架的簡單程式是自動管理生命週期階段,並允許您手動管理。JSF(JavaServer Faces)應用程式的生命週期從客戶端對頁面發出HTTP請求時開始,並在伺服器響應頁面時結束。

JSF生命週期分為兩個主要階段:

  • 執行階段
  • 渲染階段

1. 執行階段

在執行階段,當第一次請求時,構建或恢復應用程式檢視。 對於其他後續請求,執行其他操作,如應用請求引數值,對元件值執行轉換和驗證,受託管的bean

將使用元件值進行更新,並呼叫應用程式邏輯。
執行階段被進一步分成以下子階段。

  • 恢復檢視階段
  • 應用請求值階段
  • 流程驗證階段
  • 更新模型值階段
  • 呼叫應用階段
  • 渲染響應階段

      a:恢復檢視階段

       當客戶端請求一個JavaServer Faces頁面時,JavaServer Faces實現開始恢復檢視階段。 在此階段,JSF將檢視中的元件構建為請求頁面,線性事件處理程式和驗證器的檢視,並將檢視儲存在FacesContext例項中。

       如果對該頁面的請求是回發,那麼與該頁面相對應的檢視已經存在於FacesContext例項中。 在此階段,JavaServer Faces實現通過使用儲存在客戶端或伺服器上的狀態資訊來還原檢視。

      b:應用請求值階段

       在此階段,在回發請求期間恢復元件樹。 元件樹是表單元素的集合。樹中的每個元件通過使用其decode(processDecodes())方法從請求引數中提取其新值。 之後,該值將本地儲存在每個元件上。

  • 如果任何解碼方法或事件偵聽器在當前FacesContext例項上呼叫了renderResponse方法,則JavaServer Faces實現將跳過“渲染響應”階段。
  • 如果任何事件在此階段已排隊,則JavaServer Faces實現將事件廣播到有興趣的監聽器。
  • 如果應用程式需要重定向到其他Web應用程式資源或生成不包含任何JavaServer Faces元件的響應,則可以呼叫FacesContext.responseComplete()方法。
  • 如果當前請求被識別為部分請求,則從FacesContext檢索部分上下文,並應用部分處理方法。

     c:流程驗證階段

      在此階段,JavaServer Faces通過使用其validate()方法來處理在元件上註冊的所有驗證器。 它檢查指定驗證規則的元件屬性,並將這些規則與為元件儲存的本地值進行比較。 JavaServer Faces還完成了沒有將immediate屬性設定為true的輸入元件的轉換。

  • 如果任何驗證方法或事件偵聽器在當前FacesContext上呼叫了renderResponse方法,則JavaServer Faces實現將跳過“渲染響應”階段。
  • 如果應用程式需要重定向到不同的Web應用程式資源或生成不包含任何JavaServer Faces元件的響應,則可以呼叫FacesContext.responseComplete方法。
  • 如果事件在此階段已排隊,則JavaServer Faces實現將它們廣播給有興趣的監聽器。
  • 如果當前請求被識別為部分請求,則從FacesContext檢索部分上下文,並應用部分處理方法。

      d:更新模型值階段

        確保資料有效後,它遍歷元件樹,並將相應的伺服器端物件屬性設定為元件的本地值。 JavaServer Faces實現只更新輸入元件的value屬性指向bean屬性。 如果本地資料無法轉換為bean屬性指定的型別,生命週期將直接前進到“渲染響應”階段,以便重新呈現頁面並顯示錯誤。

  • 如果任何updateModels方法或任何監聽器在當前FacesContext例項上呼叫了renderResponse()方法,則JavaServer Faces實現將跳過“渲染響應”階段。
  • 如果應用程式需要重定向到其他Web應用程式資源或生成不包含任何JavaServer Faces元件的響應,則可以呼叫FacesContext.responseComplete()方法。
  • 如果任何事件在此階段已排隊,JavaServer Faces實現將它們廣播到有興趣的監聽器。
  • 如果當前請求被識別為部分請求,則從FacesContext檢索部分上下文,並應用部分處理方法。

       e:呼叫應用階段

         在此階段,JSF處理應用程式級事件,例如提交表單或連結到另一個頁面。
現在,如果應用程式需要重定向到其他Web應用程式資源或生成不包含任何JSF元件的響應,則可以呼叫FacesContext.responseComplete()方法。

之後,JavaServer Faces實現將控制轉移到“渲染響應”階段。

      f:渲染響應階段

      這是JSF生命週期的最後階段。 在此階段,JSF將構建檢視並將許可權委託給相應的資源來呈現頁面。

  • 如果這是初始請求,則頁面上表示的元件將被新增到元件樹中。
  • 如果這不是初始請求,元件已經新增到樹中,不需要再新增。
  • 如果請求是迴應,並且在應用請求值階段,過程驗證階段或更新模型值階段期間遇到錯誤,則在此階段將再次呈現原始頁面。

   如果頁面包含h:messageh:messages標籤,頁面上會顯示任何排隊的錯誤訊息。
在渲染檢視的內容之後,儲存響應的狀態,以便後續請求可以訪問它。 恢復檢視階段可以使用儲存的狀態。

 

2. 渲染階段

在此階段,請求的檢視作為對客戶端瀏覽器的響應。 檢視渲染是以HTML或XHTML生成輸出的過程。 所以,使用者可以在瀏覽器看到它。

在渲染過程中採取以下步驟。

  • 當客戶端對index.xhtml網頁進行初始請求時,編譯應用程式。
  • 應用程式在編譯後執行,併為應用程式構建一個新的元件樹,並放置在FacesContext中。
  • 使用由EL表示式表示的元件和與其關聯受託管bean屬性填充元件樹。
  • 基於元件樹。 建立了新的檢視。
  • 該檢視作為響應呈現給請求客戶端。
  • 元件樹被自動銷燬。
  • 在後續請求中,重新構建元件樹,並應用已儲存的狀態。

三、JSF託管Bean

      託管bean它是一個純Java類,它包含一組屬性和一組gettersetter方法。

  以下是託管bean方法執行的常見功能:

  • 驗證元件的資料
  • 處理元件觸發的事件
  • 執行處理以確定應用程式必須導航的下一頁
  • 它也可以作為JFS框架的模型。

1、JSF託管Bean示例:

    請看看下面一段示例程式碼 :

public class User {  
    private String name;  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }   
}

您可以通過以下方式使用此bean

  • 通過配置成XML檔案。
  • 通過使用註釋。

   a:通過XML檔案配置託管Bean:

<managed-bean>  
    <managed-bean-name>user</managed-bean-name>  
    <managed-bean-class>User</managed-bean-class>  
    <managed-bean-scope>session</managed-bean-scope>  
</managed-bean>

在xml檔案配置bean是比較舊方法。 在這種方法中,我們必須建立一個名為faces-config.xml的xml檔案,JSF提供了配置bean的標籤。

在上面的例子中,我們列出了bean-namebean-classbean-scope。 所以,它可以在專案中訪問。

   b:使用註釋配置託管Bean:

import javax.faces.bean.ManagedBean;  
import javax.faces.bean.RequestScoped;  

@ManagedBean    // Using ManagedBean annotation  
@RequestScoped  // Using Scope annotation  
public class User {  
    private String name;  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
         this.name = name;  
    }  
}

     類中的@ManagedBean註解自動將該類註冊為JavaServer Faces的資源。 這種註冊的託管bean在應用程式配置資原始檔中不需要託管bean配置項。

  @ManagedBean將bean標識為名稱屬性中指定的名稱的託管bean。如果未指定name屬性,那麼託管bean名稱將預設為簡單的類名稱,其中第一個字母小寫。 在我們的情況下是helloWorld
如果eager設定為“true”,則在請求之前建立託管bean。如果使用“lazy”初始化,只有在請求時才會建立bean。

  這是應用程式配置資原始檔方法的替代方法,並減少配置託管bean的任務。
  @RequestScoped註釋用於提供託管的範圍。 您可以使用註解來定義bean將被儲存的範圍。

@ManagedBean(name = "helloWorld", eager = true)
@RequestScoped
public class HelloWorld {

   @ManagedProperty(value="#{message}")
   private Message message;
   ...
}

 您可以對bean類使用以下範圍:

  • 應用程式(@ApplicationScoped):應用程式範圍在所有使用者中保持不變,與Web應用程式的互動。( bean只要Web應用程式生存。 它在第一個HTTP請求或Web應用程式啟動時建立,並且在@ManagedBean中設定屬性eager = true,並在Web應用程式關閉時被銷燬)。
  • 會話(@SessionScoped):會話範圍在Web應用程式中的多個HTTP請求中保持不變。(bean只要HTTP會話生存。 它在第一個HTTP請求時建立,並在HTTP會話無效時被銷燬)。
  • 檢視(@ViewScoped):在使用者與Web應用程式的單個頁面(檢視)進行互動時,檢視範圍仍然存在。(bean只要使用者在瀏覽器視窗中與同一JSF檢視進行互動即可。 它根據HTTP請求建立,並在使用者導航到其他檢視時被銷燬)。
  • 請求(@RequestScoped):在Web應用程式中的單個HTTP請求期間,請求範圍仍然存在。(bean只要HTTP請求響應就行。它根據HTTP請求建立,並在與HTTP請求相關聯的HTTP響應完成時被銷燬)。
  • 無(@NoneScoped):表示未為應用程式定義作用域。(bean與單個表示式語言(EL)求值時間一樣長。 在EL求值評估時建立,並在EL求值評估後被銷燬)。
  • 自定義(@CustomScoped):使用者定義的非標準作用域。 其值必須配置為java.util.Map,自定義範圍很少使用。(bean只要在為此範圍建立的自定義Map中的bean的條目生效)。

急切管理Bean

託管bean預設是懶惰的。 這意味著,只有在從應用程式發出請求時才會去例項化bean。
如果想自動提前強制將bean例項化,那麼可在應用程式啟動時,可以強制將bean例項化並放置在應用程式(@ApplicationScoped)範圍內。您需要將託管 bean 的eager屬性設定為true,如以下示例所示:

@ManagedBean(eager=true)

@ManagedProperty註釋

JSF是一個簡單的靜態依賴注入(DI)框架。 @ManagedProperty註釋標記被託管的bean的屬性以注入另一個受託管的Bean。

2、如何進行bean注入

我們先定義一個訊息bean,它有一個字串屬性來儲存訊息。

@ManagedBean(name="message")
@SessionScoped
public class MessageBean implements Serializable {

  private static final long serialVersionUID = 1L;

  private String sayWelcome = "Welcome to JSF 2.0";

然後我們再定義另一個託管bean,並使用@ManagedProperty註解注入MessageBean

@ManagedBean
@SessionScoped
public class UserBean implements Serializable {

  private static final long serialVersionUID = 1L;

  @ManagedProperty(value="#{message}")
  private MessageBean messageBean;

  public void setMessageBean(MessageBean messageBean) {
    this.messageBean = messageBean;
  }

例項:

     建立一個名為: InjectManagedBeans 的工程,並加入以下檔案程式碼。
以下是檔案:UserBean.java 中的程式碼 

package com.yiibai;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class UserBean implements Serializable {

  private static final long serialVersionUID = 1L;

  @ManagedProperty(value="#{message}")
  private MessageBean messageBean;

  public void setMessageBean(MessageBean messageBean) {
    this.messageBean = messageBean;
  }

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getSayWelcome(){
    //check if null?
    if("".equals(name) || name ==null){
      return "";
    }else{
      return messageBean.getSayWelcome() + name;
    }
  }

}

以下是是檔案:index.xhtml 中的程式碼 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">

    <h:body>

      <h:form>
         <h:inputText id="name" value="#{userBean.name}"></h:inputText>
         <h:commandButton value="Welcome Me">
         <f:ajax execute="name" render="output" />
         </h:commandButton>

         <h2><h:outputText id="output" value="#{userBean.sayWelcome}" /></h2>  
      </h:form>

    </h:body>
</html>

以下是檔案:MessageBean.java 中的程式碼 

package com.yiibai;
import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="message")
@SessionScoped
public class MessageBean implements Serializable {

  private static final long serialVersionUID = 1L;

  private String sayWelcome = "Welcome to JSF 2.0";

  public String getSayWelcome() {
    return sayWelcome;
  }

  public void setSayWelcome(String sayWelcome) {
    this.sayWelcome = sayWelcome;
  }

}

執行測試結果:

Tomcat啟動完成後,在瀏覽器位址列中輸入以下URL。

http://localhost:8084/InjectManagedBeans/

執行結果如下所示