0

我有一个小JSF应用程序,页面的范围是request. 我想在我的 JSF 的托管 bean 中有一个用于记录user_idpage name数据库的方法。当我将此方法添加到 bean 的构造函数时,由于页面范围为request.

当用户在登录我的应用程序后首次访问页面时,只记录一次上述详细信息的最佳方式是什么?想法是用户为每个日志记录访问的所有页面。实现这一目标的最佳方法是什么?

我的 JSF 版本是 1.1。

谢谢

4

2 回答 2

1

您可以向 bean 添加一个方法,并在页面加载时从页面调用它。例如

将此添加到页面中:

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

豆方法:

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

这样,只有在页面加载后才会调用该方法。如果您收到方法未找到错误,那么另一种选择是使用隐藏表单破解。例如:

<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>
于 2012-07-23T06:27:58.283 回答
1

因此,您希望将所有用户对站点不同页面的所有访问都登录到数据库表中,但要避免记录回发,对吗?(当用户在您的一个页面中执行操作并且接收操作的 URL 与启动操作的 URL 相同时,就会发生回发 - 这在 JSF 中很常见,特别是在 2.0 之前的版本中。 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 扩展了那个。我喜欢让我的所有托管 bean 尽可能接近 POJO 概念,因此,作为替代方案,我会考虑实现相同的逻辑,但使用绑定到阶段的PhaseListener 。RENDER_RESPONSE它将为您提供一种底层(更清洁)和通用的方法:如果有一天您想要记录动作而不是渲染,那么您将侦听器与INVOKE_APPLICATION阶段联系起来,等等。

PD:我希望您使用某种缓存或“批处理”技术将这些记录记录到您的数据库中,否则当有太多用户浏览您的网站时,您将有明显的性能影响。此外,在我自己看来,您应该将您的 JSF 版本至少更新到 1.2,并且您将避免一些烦人的错误或意外行为......

于 2012-07-23T08:39:28.457 回答