2012-07-22 76 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