JSF的很多文檔上面說,要建立一個自定義組件,需要定義繼承自UIComponentBase之類的類,然后寫decode/encode方法等等,一大套內(nèi)容,很復(fù)雜。幸好我們有其他的辦法。其實定義一個組件在大多數(shù)情況下是不用去寫這樣的代碼的。本節(jié)的內(nèi)容是一個選擇true/false兩個值得下拉框組件。定義一個這樣的組件需要做如下工作:
1.定于一個頁面,用來實現(xiàn)這個組件,主要內(nèi)容如下(其實這個頁面的內(nèi)容沒有強制要求):
<h:selectOneMenu id="#{id}" value="#{value}" rendered="#{rendered}" styleClass="#{styleClass}">
<!--是否展示null值對應(yīng)的選項-->
<c:if test="#{not empty noSelectionLabel}">
<f:selectItem itemLabel="#{noSelectionLabel}"/>
</c:if>
<f:selectItem itemLabel="#{empty trueLabel ? '是' : trueLabel}" itemValue="true"/>
<f:selectItem itemLabel="#{empty falseLabel ? '否' : falseLabel}" itemValue="false"/>
</h:selectOneMenu>
上面的代碼中的每一個#{xx},都是我們最終使用這個組件的時候用需要用屬性參數(shù)的形式傳進來的。
2.注冊Tag,需要在類路徑下的某個*.taglib.xml中增加一個注冊:
<!--這個是標記庫的namespace-->
<namespace>http://www.a.com/jsf/facelets/tags</namespace>
<!--該標記的注冊-->
<tag>
<tag-name>selectBooleanMenu</tag-name>
<source>resources/jsf/components/selectBooleanMenu.xhtml</source>
</tag>
如此,在頁面上我們就可以使用這個標記了:
<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:jsf="http://www.a.com/jsf/facelets/tags">
<body>
<h:form>
你吃或者不吃,飯就在那里:<br/>
<jsf:selectBooleanMenu value="#{someAction.booleanValue}" noSelectionLabel="請選擇" trueLabel="吃" falseLabel="不吃"/>
</h:form>
</body>
</html>
如此,自定義標記組件還是很容易的。在一個組件的頁面中(selectBooleanMenu.xhtml)你可以使用后臺任意bean。所以即使某些工作需要結(jié)合后臺的代碼來完成,你也不需要實現(xiàn)啥接口。
關(guān)于模塊化,在傳統(tǒng)的mvc中,你請求/a.do,到某ActionBean,處理,然后forward到頁面。這樣會有一個問題:假設(shè)a.do和ActionA用來處理a業(yè)務(wù),b.do和ActionB用來處理b業(yè)務(wù)。c.do集合了a,b的一些功能,那么你無法再c對應(yīng)的頁面上同時使用ActionA,ActionB。所以你要繞了。
在JSF中,一個頁面上使用表達式引用到后臺上下文中的任意Bean,要做c頁面,你在c頁面上直接引用ActionA和ActionB完成功能即可。這樣你不用做一些“混合”的東西。后臺代碼的模塊化更加容易實現(xiàn),前臺展示和后臺業(yè)務(wù)處理分離的更加清楚。