上一篇文章我大概地介紹一下基於Faceslet的JSF頁面端的構成接下來是時候說一下後台邏輯的實現啦JSF的頁面邏輯是由Managed Bean(姑且譯為托管BEAN)實現所謂的Managed Bean就是指一些由JSF運行時(Runtime)創建與管理的普通Java對象(潮流一點的叫法——POJO)
標准JSF中Managed Bean
標准的JSF中Managed Bean是在facesconfigxml中通過XML定義的例如
<managedbean>
<managedbeanname>helloBean</managedbeanname>
<managedbeanclass>
netblogjavamaxseamHelloBean
</managedbeanclass>
<managedbeanscope>request</managedbeanscope>
</managedbean>
這些XML相信不用我怎麼講解大家也知道其作用啦定義一個BEAN無論是在SpringEJB還其它的BEAN容器(Container)中無非都是這幾個元素BEAN的名稱(或者標識ID)JAVA類型和作用域JSF的Managed Bean有四個作用域如下表所示
作用域
描述
none
作用域是none的Managed Bean通常是定義一些公用的BEAN它們的創建與存儲依賴於引用它的BEAN
request
在單一的HTTP請求(Request)中被創建和保持有效
session
在HTTP的會話(Session)中被創建和保持有效可以跨請
application
存儲WEB應用的Application上下文中對於所有的請求和會話可見
可能大家對none作用域比較陌生舉個例子可能會好理解一點
<managedbean>
<managedbeanname>helloBean</managedbeanname>
<managedbeanclass>
compccwjsftrainingmanagedbeanHelloBean
</managedbeanclass>
<managedbeanscope>request</managedbeanscope>
<managedproperty>
<propertyname>messageFromOtherBean</propertyname>
<propertyclass>javalangString</propertyclass>
<value>#{messageBean}</value>
</managedproperty>
</managedbean>
<managedbean>
<managedbeanname>messageBean</managedbeanname>
<managedbeanclass>javalangString</managedbeanclass>
<managedbeanscope>none</managedbeanscope>
<value>Hello World from Another Bean!</value>
</managedbean>
這個例子定義了一個名為messageBean作用域是none的Managed Bean然後它被注入名為messageBean作用域是request的Managed Bean中因此這個messageBean的作用域會跟隨helloBean同為request另外值得一提的是上例同樣展示了如何在一個Managed Bean初始其屬性(Property)的值如何引用其它的Managed Bean
Seam中的Web Bean(相當於Managed Bean)
標准JSF的Managed Bean存在不少缺點
必須通過XML進行配置過於麻煩
貧乏的作用域上文提及標准的JSF的Managed Bean只有四種作用域nonerequestsession和application由於JSF對狀態的依賴比較強經常需要在請求之間保存應用的狀態所以很多時候我們時候都不得不使用Session作用域的Managed Bean但是眾所周知過多地使用Session會帶來很多問題如容易造成內存耗盡難於集群(Cluster)等
有監於此Seam對JSF進行了擴展並進而起草了Web Bean標准(Web Bean還在BETA階段坦白的說我也不是很了解)下面我們就來學習一下Seam的Managed Bean(官方文檔中叫Component)在這方面Seam與標准JSF有如下不同
Seam的Component既可以通過XML配置又可以通過Annotation的方式配置我個人比較偏愛Annotation的方式方便快捷能夠提高工作效率XML方式有一個好處就是可以集中管理但是因為Managed Bean配置相對比較穩定不會經常修改所以XML優勢並不會太明顯
更豐富的作用域(Seam中稱為上下文Context)Seam有種上下文可選無狀態(Stateless Context)事件(Event Context或者Request Context)頁面(Page Context)對話(Conversation Context)會話(Session Context)業務流(Business Process Context)和應用程序(Application Context)
Seam引入一種雙向注入(Binjection)的方式所謂的雙向注入就是可以將上下文中的Bean注入到另一個Bean中又或者將Bean中的屬性(Property)直接發布在上下文中
Seam的Compoenet可以直接使用EJB 的Bean
下面我們看一個簡單的Component的定義的例子
package netblogjavamaxhellosession;
import orgjbossseamScopeType;
import orgjbossseamannotationsName;
import orgjbossseamannotationsScope;
@Name(helloWB)
@Scope(ScopeTypePAGE)
public class HelloWB {
private String name;
private String message;
public String getName() {
return name;
}
public void setName(String name) {
thisname = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
ssage = message;
}
public void sayHello() {
message = Hello + name + !;
}
public void anotherEvent() {
Systemoutprintln(Another request is coming);
}
}
通過上述代碼大家可以看到有兩句Annotation定義——Name和Scope除此之外並沒有什麼特別的地方所以正是這兩個Annotation使HelloWB成為一個可以被SEAM的運行時識別的ComponentName用於定義Component的名稱是必須的Scope則用於定義Component的作用域是可選的默認值為短對話(Short Conversation)在本例中HelloWB的作用域是PagePage與Conversation都Seam的傑作在標准JSF是沒有的而且這兩個作用域是比較常用我個人比較熱衷於Page作用域所以在這裡先談一下Page
正如我前面所說JSF對狀態的依賴比較強……造成我們對Session的依賴引起了很多問題Page很大程度上解決了這個問題它可以跨請求存活只要該請求不是新的什麼請求是新的請求呢?要回答這個問題先要搞清楚什麼是POSTBACK學過ASPNET的朋友可能對POSTBACK概念比較熟悉沒學過的話不要緊POSTBACK並不是什麼深奧的東西所謂的POSTBACK就是指用戶按下頁面上的某個按鈕或表單控件將表單數據發送回到頁面自身的URL相反如果用戶是通過在地址欄中輸入URL或通過點擊頁面的鏈接訪問頁面則這個請求就是一個NONPOSTBACK的請求也即是一個新的請求
另外一些JSF專家都推薦一種叫Backing Bean的風格所謂的Backing Bean就是指一個JSF頁面對應一個Managed Bean處理頁面邏輯Page作用域非常適用這種情況因為它是與頁面一起序列化(Serialize)到浏覽器或保存在Session中如果大家還是不太明白的話請看以下的XHTML代碼
<?xml version= encoding=utf?>
<!DOCTYPE html PUBLIC //WC//DTD XHTML Transitional//EN transitionaldtd>
<html xmlns= xmlns:h=>
<head>
<meta content=text/html; charset=utf httpequiv=ContentType/>
<title>
Hello World
</title>
</head>
<body>
<h:form>
<h:outputLabel value=Name: for=itName />
<h:inputText id=itName value=#{helloWBname} />
<h:commandButton action=#{helloWBsayHello} value=Say Hello />
<h:commandButton action=#{helloWBanotherEvent} value=Another Reqeust />
<hr />
<h>
<h:outputText value=#{ssage} />
</h>
</h:form>
</body>
</html>
發布運行上述代碼大家可以看如下頁面
在輸入框中鍵入max點擊Say Hello按鈕將請求POSTBACK到Seam的組件中由於按鈕注冊了組件的監聽方法所以HelloWB的sayHello方法會被調用它將通過值綁定所得的name與Hello和!串起來賦給message屬性因此響應頁面會如下圖所示
這時候大家可以再點擊Another Request按鈕出現的結果與上圖一樣這就說明雖然發生了第二次請求name與message的同樣保持上一次的值然後大家可以再試下復制頁面地址粘貼到新窗口或新選項卡(TAB)的地址欄中按下ENTER你會發現頁面的被重置回到最初的狀態這個例子很好地演示了POSTBACK請求與NONPOSTBACK請求的區別
小結
本文粗略地介紹了一下JSF的頁面邏輯處理組件——Managed Bean還有很多關於Seam的組件知識如Bijection和Conversation等還沒有介紹只有留待以後文章了
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28005.html