2012-07-22 34 views
0

我有一個小JSF應用程序和頁面的範圍是request。我想在我的JSF的託管bean中有一個方法,用於將user_idpage name記錄到數據庫。當我將此方法添加到bean的構造函數時,由於頁面範圍爲request,因此每個方法的調用都會記錄詳細信息。堅持用戶名和頁面名稱到數據庫

當用戶在登錄我的應用程序後第一次訪問頁面時,只記錄一次上述詳細信息的最佳方式是什麼?所有頁面用戶訪問每個日誌記錄的想法。 達成此目的的最佳方法是什麼?

我的JSF版本是1.1。

感謝

+0

我大致瞭解你想問什麼...什麼你的意思是「頁面範圍」,是否有託管豆的範圍,但是......頁面? ...你在說什麼方法?你可以發佈一些代碼? – 2012-07-22 13:16:59

+0

我的意思是頁面的範圍是頁面的作用域是在'faces-config.xml'中定義的請求,會話,應用程序等。我有一個自定義方法,比如'dbbean.getpagedetails(bean.getUserId(),this.getClass()。getName()。toString());'。我希望在我的bean中有這個,但是當我在bean的構造函數中添加這個方法時,會爲頁面的每個動作調用它。我相信這是因爲範圍是'請求'。如果範圍是s'ession',它只會調用一次。所以作爲範圍是'request',這是在bean中添加此方法的最佳位置?謝謝 – user75ponic 2012-07-23 04:20:06

回答

1

您可以將方法添加到bean,並加載頁面時從頁面調用它。例如

添加到這個頁面:

<h:outputText value="#{fooBean.logUser}"/> 

豆方法:

public void logUser(){ 
    //log user and page 
} 

這樣,一旦頁面加載方法僅調用。如果你得到的方法沒有找到 錯誤,那麼另一個選擇是使用隱藏表單hack。例如:

<body onload="document.getElementById('formId:buttonId').click()"> 
    <h:form id="formId" style="display: none;"> 
     <h:commandButton id="buttonId" value="submit" action="#{fooBean.logUser()}" /> 
    </h:form> 
    ... 
</body> 
+0

一個方法可以添加到''時,我得到'logUser'' property' not found錯誤。謝謝 – user75ponic 2012-07-23 09:46:51

+0

@Polappan默認情況下,JSF會在標記中使用getter方法,您必須輸入方法的完整限定名。 fooBean.logUser()而不是fooBean.logUser。 – fareed 2012-07-23 10:15:28

+0

我相信'foobean.logUser()'可能無法在JSF 1.1中工作。當我嘗試時,我在com.sun.faces.taglib.html_basic.OutputTextTag.doStartTag(OutputTextTag.java:165)''處獲得'javax.servlet.jsp.JspException:foobean.logUser()\t'。謝謝 – user75ponic 2012-07-23 10:20:10

1

所以,你要登錄到數據庫表中的所有用戶的所有訪問不同頁面的網站,但是,避免登錄後背上,對不對? (當用戶在您的一個頁面中執行某個操作並且接收該操作的URL與啓動該操作的URL相同時發生後備事件 - 這在JSF中非常常見,特別是在2之前的版本中。 x)

因此,基本上,您需要的是識別何時發生回發,並避免在此情況下進行日誌記錄。處理回後請求時,ResponseStateManager將爲您提供一個isPostback(...)方法返回true

FacesContext context = FacesContext.getCurrentInstance(); 
ResponseStateManager rsm = context.getRenderKit().getResponseStateManager(); 
if (!rsm.isPostback(context)) { 
    // do whatever you need here 
} 

順便說一句,我不會建議把這些代碼在bean構造都不同JSF實現可能在調用bean的構造函數之後立即執行一些bean生命週期管理任務。如果您認爲邏輯應該是「bean初始化過程」的一部分,我建議將該代碼放入一個單獨的公共方法中,並註釋爲@PostConstruct註釋。但是,如果您希望在對給定頁面的每次訪問中運行該邏輯,則使用託管bean將強制您複製&粘貼每個bean中的邏輯或使用該邏輯定義一個抽象/基類並讓所有的咖啡豆延伸那個。我希望保留所有託管bean儘可能接近POJO概念,作爲替代,我會考慮實施相同的邏輯,但使用與RENDER_RESPONSE階段綁定的PhaseListener。它會給你一個下引擎蓋(更清潔)和通用的方法:如果有一天你想登錄行動代替呈現那麼你配合你的聽衆到INVOKE_APPLICATION階段,等。

Pd積:我希望你使用某種緩存或「配料」技術,這些記錄登錄到數據庫,否則你將有一個顯着的性能影響時,過多的用戶正在瀏覽您的網站。另外,在我看來,你應該更新你的JSF版本,至少,1.2,你會避免一些煩人的錯誤或意外的行爲...

+0

感謝您的詳細解釋。在我使用JSF 1.1時,我無法使用'@ PostConstruct'註釋。是這種情況,如果我不在bean的'constructor'中添加'loguser()'方法,從我的JSF頁面調用方法的最佳方式是什麼?謝謝。 – user75ponic 2012-07-23 10:12:11

+0

請注意,我不知道你是如何獲得對'dbbean'的引用。如果您無法切換到JSF 1.2,並且您正在向使用者注入'dbbean',則可以在使用者的setDBBean方法中執行該任務(但我不會推薦它)。您可以通過其他方式(從會話,servlet上下文,spring)獲得對該bean的引用,那麼我建議使用'PhaseListener'方法。 – 2012-07-23 10:37:23

+0

我在測試postBack方法時無法找到名爲rsm.isPostBack(context)的方法。謝謝。 – user75ponic 2012-07-23 10:47:26