JSF学习笔记

来源:互联网 发布:中国城市轨道交通 知乎 编辑:程序博客网 时间:2024/06/05 11:54
具体参考资料为.

http://openhome.cc/Gossip/JSF/

1.JSF表达式:

使用JSF表达式的时候可以用#{param.name}或者#{param[‘name’]}来取得

Request

facesContext(avax.faces.context.FacesContext)

view(javax.faces.component.UIViewRoot)

范围内定义的参数变量,

 

取得#{someBean.someList[0]}数组或者list类型的变量元素

 

以及基本运算#{(1==2)? 3 : 4}

 

 

 

2.国际化支持:

资源文件名称由basename加上语言与地区来组成

Basename.properties

Basename_en.properties

Basename_zh_TW.properties

沒有指定語言與地區的basename是預設的資源檔名稱,JSF會根據瀏覽器送來的Accept-Language header中的內容來決定該使用哪一個資源檔名稱,例如:

Accept-Language: zh_TW, en-US, en

如果瀏覽器送來這些header,則預設會使用繁體中文,接著是美式英文,再來是英文語系,如果找不到對應的訊息資源檔,則會使用預設的訊息資源檔。

资源文件都是用unicode编码,所以如果用中文的话要转换成unicode编码

 

是页面中使用的时候就一开始加入

<f:loadBundlebasename="messages" var="msgs"/>

然后就能用JSF表达式来使用 #{msgs.hintText}

 

还可以直接指定

<f:view locale="zh_TW">

<f:loadBundlebasename="messages" var="msgs"/>

 

或者在faces-config.xml中配置

<faces-config>

   <application>

       <local-config>

           <default-locale>en</default-locale>//一定有且只有一个

           <supported-locale>zh_TW</supported-locale>//可以多个

       </local-config>

<message-bundle>messages</message-bundle>//绑定的语言资源文件位置

    </application>

 

 .....

 </faces-config>

 

列表方式选择语言

<h:selectOneRadiovalue="#{user.locale}">

    <f:selectItem itemValue="zh_TW"

                  itemLabel="#{msgs.zh_TWText}"/>

    <f:selectItem itemValue="en"

                   itemLabel="#{msgs.enText}"/>

 </h:selectOneRadio>

 

 

 

3.Manage Bean:

JSF使用 JavaBean 來達到程式邏輯與視圖分離的目的,在JSF中的Bean其角色是屬於Backing Bean,又稱之為Glue Bean,其作用是在真正的業務邏輯Bean及UI元件之間搭起橋樑

可以在定义bean的时候设定生命周期,可以是request,session,application,view等.其中还可以设置为none.none的意思就是当程序需要一个bean的时候才生成,是使用完就直接销毁,属于一个临时的bean只能使用一次

在jsf标签上使用属性设定取值的只支持JSF表达式#{},不支持EL表达式@{}

 

 

 

如果要在其它類別中取得Bean物件,則可以先取得javax.faces.context.FacesContext,它代表了JSF目前的執行環境物件,接著嘗試取得javax.faces.el.ValueBinding物件,從中取得指定的Bean物件,例如:

FacesContext context =FacesContext.getCurrentInstance();

ValueBinding binding =

   context.getApplication().createValueBinding("#{user}");//或者是#{user.name}只取得某一个属性

UserBean user = (UserBean)binding.getValue(context);

 

 

可以在Manage Bean刚实例化的时候就设置属性

<managed-bean>

   <managed-bean-name>user</managed-bean-name>

       <managed-bean-class>

           onlyfun.caterpillar.UserBean

       </managed-bean-class>

   <managed-bean-scope>session</managed-bean-scope>

   <managed-property>

       <property-name>name</property-name>

       <value>caterpillar</value>

   </managed-property>

   <managed-property>

       <property-name>password</property-name>

       <null-value/>//null值

</managed-property>

<managed-property>

     <property-name>user</property-name>

     <value>#{user}</value>//使用spring注入IOC

    </managed-property>

 </managed-bean>

 

 

 

4.标准转换器:

转换时间类型

<h:outputTextvalue="#{user.date}">

              <f:convertDateTimepattern="dd/MM/yyyy"/>

</h:outputText>

 

<h:form>

       <h:inputText id="dateField"value="#{user.date}">

           <f:convertDateTime pattern="dd/MM/yyyy"/>

       </h:inputText>

       <h:message for="dateField" style="color:red"/>

       <br>

       <h:commandButton value="送出" action="show"/>

</h:form>

 

 

可以自己自定转换器

继承javax.faces.convert.Converter

并实现方法

public Object getAsObject(FacesContextcontext,

                           UIComponentcomponent,

                           String str);

 publicString getAsString(FacesContext context,

                           UIComponentcomponent,

                           Object obj);

 

 

public class UserConverter implementsConverter

并且要告诉JSF,就是在faces-config.xml中声明,也可以不用声明,但是在bean中定义并实体化这个转化器

<converter>

       <converter-id>onlyfun.caterpillar.User</converter-id>

       <converter-class>

           onlyfun.caterpillar.UserConverter

       </converter-class>

</converter>

 

使用:

<h:outputText value="#{guest.user}"

                  converter="onlyfun.caterpillar.User"/>

 

<h:form>

        <h:inputTextid="userField"

                    value="#{guest.user}"

                    converter="onlyfun.caterpillar.User"/>

        <h:messagefor="userField" style="color:red"/>

        <br>

        <h:commandButtonvalue="送出"action="show"/>

    </h:form>

 

或者

<h:inputText id="userField"value="#{guest.user}">

     <f:converterconverterId="onlyfun.caterpillar.User"/>

 </h:inputText>  

 

 

使用bean实例化的转换器

<h:inputText id="userField"

    value="#{guest.user}"

     converter="#{guest.converter}"/>

 

 

 

5.验证器:

语法校验:

<h:inputSecretvalue="#{user.password}" required="true">

            <f:validateLength minimum="6"/>

</h:inputSecret>

 

<h:messages layout="table"style="color:red"/>

這一次在錯誤訊息的顯示上,我們使用<h:messages>標籤,當有驗證錯誤發生時,相關的錯誤訊息會收集起來,使用<h: messages>標籤可以一次將所有的錯誤訊息顯示出來。可以使用for为指定ID的组件显示信息

 

自定义校验器和自定义转换器的流程差不多,方式也一样

实现javax.faces.validator.Validator实现validate(1,2,3)方法

三个参数分别是信息的级别,信息概述,详细信息

并抛出ValidatorException当有错误发生的时候

 

 

 

6.错误信息处理:

可以让从程序输出的信息也是国际化

String message = rsBundle.getString(

                     "onlyfun.caterpillar.message2");

 Object[] params = {"param1","param2"};

 message =java.text.MessageFormat.format(message, params);

 

 FacesMessage facesMessage = new FacesMessage(

              FacesMessage.SEVERITY_FATAL,message, message);

....

 

如此一來,在顯示訊息時,onlyfun.caterpillar.message2的{0}與{1}的位置就會被"param1"與"param2"所取代

onlyfun.caterpillar.message2=This ismessage2 with {0} and {1}.//属性文件信息

 

可以重新自定义标签,如校验转换标签.具体可以见

http://openhome.cc/Gossip/JSF/CustomConverterValidatorTag.htm

 

 <f:attribute name="pattern"value=".+[0-9]+"/>这个标签是设置attribute属性

 

 

http://openhome.cc/Gossip/JSF/

 

 

6.动作事件

<h:commandButton value="送出" actionListener="#{user.verify}" action="#{user.outcome}"/>

这个的意思就是JSF会检查是否指定了actionListener然后再检查是否制定了动作方法.就是先执行actionListener,然后再执行action中的方法其中actionListener中的方法都是传递一个ActionEven e的参数进去,可以通过这个参数获得源.

也可以自定义一个ActionListener,只需实现importjavax.faces.event.ActionListener;

然后实现

public void processAction(ActionEvent e) {

 

    }

就可以在标签中如下指定

<h:commandButton value="送出"action="#{user.outcome}">

   <f:actionListenertype="onlyfun.caterpillar.LogHandler"/>

   <f:actionListenertype="onlyfun.caterpillar.VerifyHandler"/>

 </h:commandButton>

效果同在属性中添加actionListener一样

 

 

即使事件:

在JSF的事件模型中會有所謂即時事件,導因於Web應用程式的先天特性不同於GUI程式,所以JSF的事件模式與GUI程式的事件模式仍有相當程度的不同,一個最基本的問題正因為HTTP無狀態的特性,使得Web應用程式天生就無法直接喚起伺服端的特定物件。

所有的物件喚起都是在伺服端執行的,至於該喚起什麼物件,則是依一個基本的流程:

具体的流程处理可以参考:

http://www.ibm.com/developerworks/cn/java/j-jsf2/

回復畫面(Restore View)

依客戶端傳來的session資料或伺服端上的session資料,回復JSF畫面元件。

套用請求值(Apply Request Values)

JSF畫面元件各自獲得請求中的值屬於自己的值,包括舊的值與新的值。

執行驗證(Process Validations)

轉換為物件並進行驗證。

更新模型值(Update Model Values)

更新Bean或相關的模型值。

喚起應用程式(Invoke Application)

執行應用程式相關邏輯。

繪製回應畫面(Render Response)

 

對於動作事件(ActionEvent)來說,元件的動作事件是在套用請求值階段就生成ActionEvent物件了,但相關的事件處理並不是馬上進行,ActionEvent會先被排入佇列,然後必須再通過驗證、更新模式值階段,之後才處理佇列中的事件。

 

 

存在一种情况就是你在账号密码中输入了错误的值,或者说没有输入值,但是你需要另外一个表单或者处理在服务端处理,但是他们都在同一个表单中处理的时候如何才能是这个特殊的提交后不让服务器处理错误的账号密码验证因为可能根本就什么都没有输入,只是单纯的填入一些字符.这样的话可以在那个特殊的提交上设置属性immediate属性为true,那么服务器就会直接跳过進行驗證、更新模型值(managerBean),簡單的說,就這個程式來說,您在輸入欄位與密碼欄位中填入的值,不會影 響您的user.name與user.password。因为那2个输入栏中的值是没有在服务器中处理的,只处理了有immediate属性的那个提交

 

 

7.值变事件

这个时间就是当有值发生变化的时候就出发事件处理,在服务端处理的相关方法(ManagerBean中)要带有一个参数如下:

public void changeLocale(ValueChangeEventevent) {

       if(locale.equals("en"))

           locale = "zh_TW";

       else

           locale = "en";

}

添加的属性是

valueChangeListener="#{user.changeLocale}

 

可以添加JS代码,让发生改变的时候立刻提交表单

onchange="this.form.submit();"

 

 

 

或者是自己自己实现自己的值变类

实现javax.faces.event.ValueChangeListener并实现方法

public voidprocessValueChange(ValueChangeEvent event) {

        ....

    }

 

然后使用的时候如下

<h:selectOneMenuvalue="#{user.locale}"

                 onchange="this.form.submit();">

     <f:valueChangeListener

             type="onlyfun.caterpillar.SomeListener"/>

     <f:selectItemitemValue="zh_TW" itemLabel="Chinese"/>

     <f:selectItem itemValue="en"itemLabel="English"/>

 </h:selectOneMenu>

 

 

 

当action返回的字符串在配置文件中没有相应的映射那么会导致重新加载当前的视图

 

 

 

 

 

8.Phase事件

所谓phase事件就是指可以在jsf执行的5个流程的任意一个流程执行前或执行后执行一个动作.或者是在任意动作执行后都执行动作

有以下选择:

PhaseId.RESTORE_VIEW

PhaseId.APPLY_REQUEST_VALUES

PhaseId.PROCESS_VALIDATIONS

PhaseId.UPDATE_MODEL_VALUES

PhaseId.INVOKE_APPLICATION

PhaseId.RENDER_RESPONSE

PhaseId.ANY_PHASE

 

 

只需要实现PhaseListener,并实现3个方法

importjavax.faces.event.PhaseEvent;

importjavax.faces.event.PhaseId;

importjavax.faces.event.PhaseListener;

 

public classShowPhaseListener implements PhaseListener {

 

    public void beforePhase(PhaseEvent event) {

       String phaseName = event.getPhaseId().toString();

        System.out.println("Before "+ phaseName);

    }

 

    public void afterPhase(PhaseEvent event) {

        String phaseName =event.getPhaseId().toString();

        System.out.println("After " +phaseName);

    }

 

    public PhaseId getPhaseId() {

        return PhaseId.ANY_PHASE;

    }

}

 

 

编写完方法后然后再向配置文件中的lifecycle注册

<faces-config>

    <lifecycle>

        <phase-listener>

           onlyfun.caterpillar.ShowPhaseListener

        </phase-listener>

    </lifecycle>

    ......

</faces-config>

 

那么根据以上的的phase事件,执行每个jsf流程都会执行动作,打印出相应id

 

 

 

9.输出类型标签

outputFormat

產生指定的文字訊息,可以搭配<f:param>來設定訊息的參數以格式化文字訊息,例如:

 <f:loadBundle basename="messages"var="msgs"/>

 <h:outputFormatvalue="#{msgs.welcomeText}">

     <f:param value="Hello"/>

     <f:param value="Guest"/>

 </h:outputFormat>

 

如果您的messages.properties包括以下的內容:

 welcomeText={0}, Your name is {1}.

 

則{0}與{1}會被取代為<f:param>設定的文字,最後顯示的文字會是:

 Hello, Your name is Guest.

 

另一個使用的方法則是:

 <h:outputFormat value="{0}, Your nameis {1}.">

     <f:param value="Hello"/>

     <f:param value="Guest"/>

 </h:outputFormat>

 

 

10.输入类型标签

輸入類標籤包括了inputText、inputTextarea、inputSecret、 inputHidden,分別舉例說明如下:

 

inputText

顯示單行輸入欄位,即輸出<input> HTML標籤,其type屬性設定為text,例如:

 <h:inputText value="#{user.name}"/>

 

inputTextarea

顯示多行輸入文字區域,即輸出<textarea> HTML標籤,例如:

 <h:inputTextareavalue="#{user.command}"/>

 

inputSecret

顯示密碼輸入欄位,即輸出<input> HTML標籤,其type屬性設定為password,例如:

 <h:inputSecretvalue="#{user.password}"/>

 

您可以設定redisplay屬性以決定是否要顯示密碼欄位的值,預設是false。

 

inputHidden

隱藏欄位,即輸出<input> HTML標籤,其type屬性設定為hidden,隱藏欄位的值用於保留一些訊息於客戶端,以在下一次發送表單時一併送出,例如:

 <h:inputHiddenvalue="#{user.hiddenInfo}"/>

 

 

 

11.选择类型标签

 

<h:selectOneRadiovalue="#{user.education}">

   <f:selectItem itemLabel="高中" itemValue="高中"/>

   <f:selectItem itemLabel="大學" itemValue="大學"/>

   <f:selectItem itemLabel="研究所以上" itemValue="研究所以上"/>

 </h:selectOneRadio><p>

 

<h:selectBooleanCheckboxvalue="#{user.aggree}"/>

 

 

您也可以設定layout屬性,可設定的屬性是lineDirection、pageDirection,預設是lineDirection,也就是由左到右來排列選項,如果設定為pageDirection,則是由上至下排列選項,例如設定為:

 <h:selectOneRadio layout="pageDirection"

                  value="#{user.education}">

   <f:selectItem itemLabel="高中" itemValue="高中"/>

   <f:selectItem itemLabel="大學" itemValue="大學"/>

   <f:selectItem itemLabel="研究所以上" itemValue="研究所以上"/>

 </h:selectOneRadio><p>

 

則外觀如下:

 

 

<h:selectOneListbox>、<h: selectOneMenu>的設定方法類似於<h: selectOneRadio>,以下分別列出<h:selectOneListbox>、<h: selectOneMenu>的外觀:

 

 

 

 

<h:selectManyCheckbox>、<h:selectManyListbox>、<h: selectManyMenu>

這三個標籤提供使用者複選項目的功能,一個<h:selectManyCheckbox>例子如下:

 <h:selectManyCheckbox layout="pageDirection"

                      value="#{user.preferColors}">

     <f:selectItem itemLabel="紅"itemValue="false"/>

     <f:selectItem itemLabel="黃"itemValue="false"/>

     <f:selectItem itemLabel="藍"itemValue="false"/>

 </h:selectManyCheckbox><p>   

 

value所綁定的屬性必須是陣列或集合(Collection)物件,在這個例子中所使用的是boolean陣列,例如:

 package onlyfun.caterpillar;

 

 public class UserBean {

    private boolean[] preferColors;

 

    public boolean[] getPreferColors() {

        return preferColors;

    }

 

    public void setPreferColors(boolean[]preferColors) {

        this.preferColors = preferColors;

    }

 

    ......

 }

 

如果是其它型態的物件,必要時必須搭配轉換器(Converter)進行字串與物件之間的轉換。

 

下圖是<h:selectManyCheckbox>的外觀,這是將layout設定為pageDirection的外觀:

 

 

<h:selectManyListbox>的設定方法類似,其外觀如下:

 

 

<h:selectManyMenu>在不同的瀏覽器中會有不同的外觀,在Mozilla Firefox中是這樣的:

 

 

在Internet Explorer則是這樣的:

 

 

也可以直接使用backing bean中的值来绑定固定的selectItems

<h:selectOneRadiovalue="#{user.education}">

     <f:selectItemsvalue="#{user.educationItems}"/>

 </h:selectOneRadio>

user.educationItems可以是List或者数组.

 

 

您也可以提供一個傳回Map物件的方法,Map的key-value會分別作為選項的label-value,例如:

 <h:selectManyCheckboxlayout="pageDirection"

                      value="#{user.preferColors}">

    <f:selectItemsvalue="#{user.preferColorItems}"/>

 </h:selectManyCheckbox><p> 

 

 

您要提供下面的程式來搭配上面這個例子:

 ....

    private Map preferColorItems;

   

    public Map getPreferColorItems() {

        if(preferColorItems == null) {

            preferColorItems = new HashMap();

            preferColorItems.put("紅", "Red");

            preferColorItems.put("黃", "Yellow");

            preferColorItems.put("藍", "Blue");

        }

       

        return preferColorItems;

}

 

 

 

 

12.表格

<h:dataTable>的value值綁定的對象可以是以下的型態:

陣列

java.util.List的實例

java.sql.ResultSet的實例

javax.servlet.jsp.jstl.sql.Result的實例

javax.faces.model.DataModel的實例

 

 

 

表格的表头,表尾

JSF支援兩種facet:header與footer。分別用以設定表格的表頭與表尾文字,一個設定 的例子如下:

 <h:dataTablevalue="#{tableBean.userList}" var="user">

    <h:column>

        <f:facet name="header">

            <h:outputTextvalue="Name"/>

        </f:facet>

        <h:outputTextvalue="#{user.name}"/>

        <f:facet name="footer">

            <h:outputTextvalue="****"/>

        </f:facet>

    </h:column>

    <h:column>

        <f:facet name="header">

            <h:outputTextvalue="Password"/>

        </f:facet>               

        <h:outputTextvalue="#{user.password}"/>

        <f:facet name="footer">

            <h:outputTextvalue="****"/>

        </f:facet>

    </h:column>

 </h:dataTable>

 

所產生的表格如下所示:

可以设定css

 

<h:dataTablevalue="#{tableBean.userList}" var="user"

                styleClass="orders"

               headerClass="ordersHeader"

               rowClasses="evenColumn,oddColumn">

 


0 0