javascript
jsf教程_JSF范围教程– JSF / CDI会话范围
jsf教程
會話作用域跨越多個(gè)HTTP請求-響應(yīng)周期(理論上是無限的)。
當(dāng)您需要每個(gè)HTTP請求-響應(yīng)周期進(jìn)行一次交互時(shí),請求作用域在任何Web應(yīng)用程序中都非常有用。 但是,當(dāng)您需要對屬于用戶會話的任何HTTP請求-響應(yīng)周期可見的對象時(shí),則需要一個(gè)會話范圍 ; 在這種情況下,只要HTTP會話存在,該bean就一直存在。 會話作用域允許您創(chuàng)建對象并將其綁定到會話。 它在會話中涉及此bean的第一個(gè)HTTP請求時(shí)創(chuàng)建,并在HTTP會話無效時(shí)銷毀。 請求范圍存在于JSF和CDI中,并且以相同的方式起作用。 它可以用于非富AJAX和非AJAX請求。
會話范圍注釋
JSF :JSF請求范圍注釋是@SessionScoped ( javax.faces.bean.SessionScoped )。 具有此范圍的bean應(yīng)該使用@ManagedBean ( javax.faces.bean.ManagedBean )進(jìn)行注釋。 默認(rèn)范圍是@RequestScope 。
CDI :CDI請求范圍注釋為@SessionScoped ( javax.enterprise.context.SessionScoped )。 具有此范圍的bean應(yīng)該用@Named ( javax.inject.Named )注釋。 對于CDI托管bean( @Named ),默認(rèn)范圍是@Dependent偽作用域。
簡單的例子
// index.xhtml <h:body> <h4>Same view after submit (index.xhtml):</h4><h:form><h:commandButton value="Count" action="#{countBean.countActionVoid()}"/></h:form>Current value: #{countBean.count}<h4>Forward to another view after submit (count.xhtml):</h4><h:form><h:commandButton value="Count" action="#{countBean.countActionAndForward()}"/></h:form>Current value: #{countBean.count}<h4>Redirect to another view after submit (count.xhtml):</h4><h:form><h:commandButton value="Count" action="#{countBean.countActionAndRedirect()}"/></h:form>Current value: #{countBean.count}<h4>AJAX :</h4><h:form><h:commandButton value="Count" action="#{countBean.countActionVoid()}"><f:ajax render="currentValueId"/></h:commandButton></h:form><h:outputText id="currentValueId" value="Current value: #{countBean.count}"/> </h:body>// count.xhtml <h:body> Current value: #{countBean.count} </h:body>// CountBean.java import java.util.logging.Logger; import java.io.Serializable; // for JSF import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; // for CDI import javax.inject.Named; import javax.enterprise.context.SessionScoped;// JSF vs CDI @ManagedBean @Named @SessionScoped @SessionScoped public class CountBean implements Serializable {private static final Logger LOG = Logger.getLogger(CountBean.class.getName());private int count;public CountBean() {LOG.info("CountBean#Initializing counter ...");count = 0;}public void countActionVoid() {LOG.info("CountBean#countActionVoid() - Increasing counter ...");count++;}public String countActionAndForward() {LOG.info("CountBean#countActionAndForward() - Increasing counter ...");count++;return "count";}public String countActionAndRedirect() {LOG.info("CountBean#countActionAndRedirect() - Increasing counter ...");count++;return "count?faces-redirect=true;";}public int getCount() {return count;}public void setCount(int count) {this.count = count;} }完整的應(yīng)用程序可在此處獲得 。
因此,當(dāng)通過AJAX,在同一視圖(或另一個(gè)視圖)或重定向機(jī)制中通過前進(jìn)機(jī)制返回時(shí), count數(shù)值將增加1 。 這揭示了兩個(gè)方面:
- 每個(gè)用戶會話一次調(diào)用CountBean構(gòu)造函數(shù)以創(chuàng)建一個(gè)新實(shí)例。 這意味著count僅用0初始化一次。 當(dāng)前用戶會話中觸發(fā)的其他請求將使用此CountBean實(shí)例。 我們說每個(gè)用戶都有一個(gè)CountBean實(shí)例。
- 會話范圍在轉(zhuǎn)發(fā)或重定向時(shí)不會丟失對象的狀態(tài)。 在session被銷毀之前,對象的狀態(tài)一直可用(例如,會話超時(shí),無效等)。
基本上,在將數(shù)據(jù)提交到會話作用域的bean時(shí)必須要注意。 只要當(dāng)前的用戶會話,提交的數(shù)據(jù)將“有效”。 因此,一個(gè)好的實(shí)踐將告訴您不要在會話中存儲大量數(shù)據(jù),尤其是在內(nèi)存是關(guān)鍵資源的情況下。
實(shí)現(xiàn)可序列化
JSF和CDI托管bean應(yīng)該聲明為Serializable ( implements Serializable )。 這是必需的,因?yàn)槿萜骺赡軙挃?shù)據(jù)持久化(序列化)到硬盤上。 這樣,容器可以管理重載之類的緊急情況,或者僅與集群中的其他服務(wù)器共享數(shù)據(jù),或者在服務(wù)器重啟期間恢復(fù)會話。
會話范圍編程訪問
您可以通過編程方式與會話范圍進(jìn)行交互,如下所示:
- 訪問會話范圍圖 // JSF 2.0-2.2 FacesContext context = FacesContext.getCurrentInstance(); Map<String, Object> requestMap = context.getExternalContext().getSessionMap();// JSF 2.3 @Inject @SessionMap private Map<String, Object> sessionMap;// OmniFaces Map<String, Object> requestmap = Faces.getSessionMap();
- 獲取會話范圍的屬性 // JSF 2.0 - 2.3 sessionMap.put(name, value);// OmniFaces Faces.setSessionAttribute(name, value);
- 刪除會話范圍的屬性 // JSF 2.0-2.3 Object value = sessionMap.remove(name);// OmniFaces <T> value = Faces.removeSessionAttribute(name);
! 在JSF頁面中,可以使用隱式對象#{sessionScope} (例如,獲取CountBean實(shí)例: #{sessionScope.countBean} )。
其中,會話映射將包含在會話范圍( @SessionScoped (JSF/CDI ))下聲明的托管bean實(shí)例。
如果是JSF托管Bean(不是CDI托管Bean,在這種情況下,密鑰非常復(fù)雜),則可以通過它們的名稱輕松識別此類Bean,這些名稱在會話映射中成為密鑰。 因此,您將能夠在會話映射中的countBean項(xiàng)下找到該JSF托管Bean的實(shí)例。 如果通過@ManagedBean (名稱=“ some_name ”)指定bean名稱,則some_name將成為會話映射中的鍵。 因此,通過會話映射,您可以訪問會話范圍內(nèi)的JSF托管Bean的屬性,如下所示:
String count = ((CountBean)(Faces.getSessionAttribute("countBean/some_name"))).getCount();這樣做也是完全合法的(這是指當(dāng)前的bean):
@ManagedBean(name="some_name") ... String bean_name = getClass().getAnnotation(ManagedBean.class).name(); int count = ((CountBean)(Faces.getSessionAttribute(bean_name))).getCount();現(xiàn)在,您可以輕松地了解如何使用存儲在會話映射中的托管bean。
使用
通常,在托管bean中,我們需要編寫一個(gè)帶有@PostConstruct注釋的方法,以基于注入的工件來完成初始化任務(wù)。 換句話說,@ @PostConstruct注釋用于需要依賴注入完成以執(zhí)行任何初始化之后需要執(zhí)行的方法。 當(dāng)初始化不涉及注入的工件時(shí),可以使用構(gòu)造函數(shù)進(jìn)行初始化。 對于會話作用域的Bean,在創(chuàng)建會話作用域的Bean實(shí)例之后,將僅調(diào)用一次用@PostConstruct注釋的方法。
JSF托管bean示例:
import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped;@ManagedBean @SessionScoped public class InitBean implements Serializable{private int init;public InitBean() {init = 5;}public int getInit() {return init;}public void setInit(int init) {this.init = init;} }import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped;@ManagedBean @SessionScoped public class CountBean implements Serializable {@ManagedProperty("#{initBean}")private InitBean initBean;@PostConstructpublic void init(){LOG.info("CountBean#Initializing counter with @PostConstruct ...");count = initBean.getInit();}public void setInitBean(InitBean initBean) {this.initBean = initBean;} ... }CDI托管Bean示例:
import java.io.Serializable; import javax.enterprise.context.SessionScoped; import javax.inject.Named;@Named @SessionScoped public class InitBean implements Serializable {private int init;public InitBean() {init = 5;}public int getInit() {return init;}public void setInit(int init) {this.init = init;} }import java.io.Serializable; import javax.inject.Inject; import javax.enterprise.context.SessionScoped; import javax.inject.Named;@Named @SessionScoped public class CountBean implements Serializable {@Injectprivate InitBean initBean;@PostConstructpublic void init(){LOG.info("CountBean#Initializing counter with @PostConstruct ...");count = initBean.getInit();}... }注入和會話作用域bean
JSF :對于JSF托管的bean,注入是通過@ManagedProperty完成的。 例如:
CDI :對于CDI托管的bean,注入是通過@Named完成的。 例如:
JSF和CDI混合:可以在JSF中注入CDI(反之亦然!)
JSF托管Bean限制:
! 作為JSF中的一般規(guī)則,請勿使用壽命比調(diào)用它的對象更短的對象。 換句話說,請使用壽命與被注入對象相同或更長的對象。 違反此規(guī)則將導(dǎo)致JSF異常。 根據(jù)此規(guī)則,在JSF會話范圍內(nèi)的受管Bean中,您可以注入會話和應(yīng)用程序受管Bean,但不能請求或查看受管Bean。 可以將JSF托管Bean注入其他JSF托管Bean中。
CDI托管Bean限制:
! 當(dāng)使用壽命比調(diào)用它的對象更短的對象時(shí)(例如,將請求范圍的Bean注入會話范圍的Bean),CDI將用例分類為不匹配的注入,并通過CDI解決問題代理。 對于每個(gè)請求,CDI代理都會重新建立與請求范圍的Bean的實(shí)時(shí)實(shí)例的連接。 可以將CDI托管bean注入JSF托管bean中。
以編程方式配置JSF會話范圍的托管Bean
從JSF 2.2開始,我們可以以編程方式重現(xiàn)faces-config.xml的內(nèi)容。 對于會話范圍內(nèi)的受管bean,相關(guān)的代碼片段為:
@Override public void populateApplicationConfiguration (Document toPopulate) {String ns = toPopulate.getDocumentElement().getNamespaceURI();Element managedbeanEl = toPopulate.createElementNS(ns, "managed-bean");Element managedbeannameEl = toPopulate.createElementNS(ns, "managed-bean-name");managedbeannameEl.appendChild(toPopulate.createTextNode("countBean"));managedbeanEl.appendChild(managedbeannameEl);Element managedbeanclassEl = toPopulate.createElementNS(ns, "managed-bean-class");managedbeanclassEl.appendChild(toPopulate.createTextNode("beans.CountBean"));managedbeanEl.appendChild(managedbeanclassEl);Element managedbeanscopeEl = toPopulate. createElementNS(ns, "managed-bean-scope");managedbeanscopeEl.appendChild(toPopulate. createTextNode("session"));managedbeanEl.appendChild(managedbeanscopeEl);...// programmatic create managed-property...toPopulate.getDocumentElement().appendChild(managedbeanEl); }完整的應(yīng)用程序可以在精通JSF 2.2的書中看到。
在XML文件中配置JSF請求范圍的托管Bean
通過XML配置,您可以使用舊的JSF 1.x機(jī)制在普通的faces-config.xml文件中定義托管bean。 例如:
... <managed-bean><managed-bean-name>countBean</managed-bean-name><managed-bean-class>beans.CountBean</managed-bean-class><managed-bean-scope>session</managed-bean-scope>...<!-- managed bean properties --> via <managed-property/>... </managed-bean> ...受管bean應(yīng)該在單獨(dú)的XML文件中定義,因?yàn)閒aces-config.xml用于設(shè)置應(yīng)用程序級別的配置。 基本上,如果您喜歡這種方法,請創(chuàng)建一個(gè)新的XML文件,并將受管bean的詳細(xì)信息放入其中。 最后,通過web.xml文件中的javax.faces.CONFIG_FILES上下文參數(shù)聲明XML文件。
... <context-param><param-name>javax.faces.CONFIG_FILES</param-name><param-value>WEB-INF/my-manage-beans.xml</param-value> </context-param> ...在下一篇關(guān)于JSF / CDI應(yīng)用程序范圍的文章中見。
翻譯自: https://www.javacodegeeks.com/2015/11/jsf-scopes-tutorial-jsfcdi-session-scope.html
jsf教程
總結(jié)
以上是生活随笔為你收集整理的jsf教程_JSF范围教程– JSF / CDI会话范围的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 800米跑步标准成绩(800米跑步的各项
- 下一篇: 直降 1701 元清仓:小米 12S 手