当前位置: 首页 > 知识库问答 >
问题:

JSF捕获会话超时

薛弘济
2023-03-14

是否有可能“拦截”会话超时?

我尝试了HttpSessionListener,但据我所知,当调用HttpSessionListener.session毁灭()'方法时,会话已经被摧毁。(所以我没有机会确定用户,拥有超时的会话)

另一个选项是PhaseListener,在restoreView阶段检查会话是否是“新的”。

但是,我需要在会话超时的“第二天”执行一些操作-不在以后的刷新中执行,也不在以后的登录中执行。

(背景:需要删除某些对象的锁,用户可能在运行超时时一直在处理。)

有没有办法做到这一点?

编辑:尝试1:在有问题的SessionBean上使用@PreDestroy:

@SessionScoped
@Named
public class SessionBean1 implements Serializable {
   ...
  @PostConstruct
  private void pconstruct(){
     System.out.println("PostConstructing Session Bean 1");
  }
  @PreDestroy
  public void destroy(){
     System.out.println("PreDestroying Session Bean 1");
  } 
}

 public class SessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        //nothing to do right here.
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("Session Listener says 'destroyed'.");
    }
} 

预期结果:当会话超时或用户注销时,destroy()将被校准。

结果:两者都没有发生。

22:29:11,199 INFO  [stdout] (http--0.0.0.0-8090-1) ---- Started RESTORE_VIEW 1 ----
22:29:11,208 INFO  [stdout] (http--0.0.0.0-8090-1) ---- Started RENDER_RESPONSE 6 ----
22:29:11,890 INFO  [stdout] (http--0.0.0.0-8090-1) PostConstructing Session Bean 1
22:29:11,898 INFO  [stdout] (http--0.0.0.0-8090-1) -- Finished Request --
22:30:11,905 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Session Listener says 'destroyed'.

尝试2:尝试在SessionListener内截获会话超时,这显然会注意到超时:

public class SessionListener implements HttpSessionListener {

    @Inject
    private MySession mySession;

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("Destroying Session of owner: " + mySession.getCurrentUser().getShortName());
    }
}

预期结果:仍然可以访问会话bean。

结果:“ContextNotActivieException”:

22:38:57,948 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/test]] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Session event listener threw exception: org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
    at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:598) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:71) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:79) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at my.namespace.test$Proxy$_$$_WeldClientProxy.getCurrentUser(MySession$Proxy$_$$_WeldClientProxy.java) [classes:]
    at my.namespace.listener.SessionListener.sessionDestroyed(SessionListener.java:16) [classes:]
    at org.apache.catalina.session.StandardSession.expire(StandardSession.java:690) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:585) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:390) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:375) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1316) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1601) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1610) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1610) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1590) [jbossweb-7.0.13.Final.jar:]
    at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_33]

尝试3:检查会话属性是否有要使用的内容:

public class SessionListener implements HttpSessionListener {

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        int i=0;
        while (se.getSession().getAttributeNames().hasMoreElements()){
            String name = se.getSession().getAttributeNames().nextElement();
            System.out.println("Checking " + name);
            Object value = se.getSession().getAttribute(name);
            System.out.println("value was: " + value);

            if (i++ == 20){
                break;
            }
        }
    }


    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // nothing to do right here.
    }
}

预期结果:可用属性列表。

结果:无限循环:

22:47:48,025 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Checking org.jboss.weld.context.conversation.ConversationIdGenerator
22:47:48,025 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) value was: org.jboss.weld.context.conversation.ConversationIdGenerator@1edd87d
22:47:48,026 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Checking org.jboss.weld.context.conversation.ConversationIdGenerator
22:47:48,027 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) value was: org.jboss.weld.context.conversation.ConversationIdGenerator@1edd87d
22:47:48,028 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Checking org.jboss.weld.context.conversation.ConversationIdGenerator
22:47:48,029 INFO  [stdout] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) value was: org.jboss.weld.context.conversation.ConversationIdGenerator@1edd87d

编辑:

最后,我使用了HttpSessionListener,并在SessionMap:FacesContext中创建了一个手动条目,与所有会话范围的bean一起。getCurrentInstance()。getExternalContext()。getSessionMap()。放置(“用户id”,5)

可以在SessionListener中访问此值,并允许我关闭给定用户的所有锁。

共有2个答案

柴宝
2023-03-14

我这样做的方法是使UserBean本身成为一个HttpSessionListener。然后,它仍然拥有自己的所有状态,因此它知道自己是谁,而不管调用回调时会话是否仍然具有属性。

唐永春
2023-03-14

我尝试了HttpSessionListener,但据我所知,当调用HttpSessionListener.session毁灭()'方法时,会话已经被破坏。(所以我没有机会确定用户,拥有超时的会话)

我不确定这是怎么形成问题的。您仍然可以通过HttpSessionEvent参数获得具体的HttpSession实例,您可以在该实例上调用getAttribute()方法等,以便在登录用户存储为会话属性的情况下检查该用户。

User user = (User) event.getSession().getAttribute("user");
// ...

更新:根据您的失败尝试:

>

您不应该获取已注入的@命名的实例。您应该直接获取具体实例作为会话属性。对具体的托管bean名称使用HttpSession#getAttribute()

在每次迭代过程中都要重新创建迭代器。您应该创建它一次,并在每次迭代中重用它。将getAttributeNames()放在之外,而。这个问题与JSF/Servlet无关,只与基本Java相关。

 类似资料:
  • 问题内容: 我正在使用spring / spring-security 3.1,希望在用户注销(或会话超时)时采取一些措施。我设法完成了注销操作,但对于会话超时,我无法使其正常工作。 在web.xml中,仅指定了ContextLoaderListener(这可能是问题吗?),当然还有DelegatingFilterProxy。 我使用这样的自动配置。 当用户单击注销时,将调用注销处理程序,这将对数

  • 我使用的是spring/spring-security 3.1,希望在用户注销时(或者会话超时)采取一些操作。我设法完成了注销的操作,但对于会话超时,我无法使其工作。 处理它的一种方法是在用户登录时将用户名注入会话,然后使用普通的httpsessionlistener,并在会话超时时执行相同的操作。 spring security是否有类似的方法,以便当spring发现会话要超时时,我可以挂接在那

  • 我在解决如何正确处理JSF中会话的自动销毁方面遇到了困难。当然,此时,容器会使会话失效,从而也会在会话范围的bean上调用@PreDestroy方法。 在某些会话范围bean的预销毁中,我们正在注销一些侦听器,如下所示: 然而,getWS()方法实际上试图获取对另一个会话范围bean的引用,但失败了,如返回null。Ryan Lubke认为,后者似乎是正常的JSF行为: 我们遵守这里的规范。我不确

  • 在 HTTP 协议中,当客户端不再处于活动状态时没有显示的终止信号。这意味着当客户端不再处于活跃状态时可以使用的唯一机制是超时时间。 Servlet 容器定义了默认的会话超时时间,且可以通过 HttpSession 接口的 getMaxInactiveInterval 方法获取。开发人员可以使用HttpSession 接口的 setMaxInactiveInterval 方法改变超时时间。这些方法

  • 问题内容: 我正在Glassfish v3上开发JSF 2.0应用程序,并且试图处理ViewExpiredException。但是无论我做什么,我总会得到一个Glassfish错误报告,而不是我自己的错误页面。 为了模拟VEE的发生,我将以下函数插入到支持bean中,从而触发了VEE。我正在通过commandLink从我的JSF页面触发此功能。代码: 最初,我只是通过将一个错误页面添加到我的web

  • 问题内容: 我在用户登录时创建会话,如下所示: 如何在X分钟的会话上指定超时,然后在达到X分钟后让它执行功能或页面重定向? 编辑:我忘了提及由于不活动,我需要会话超时。 问题答案: 首先,存储用户最后一次发出请求的时间 在后续请求中,检查他们多久之前提出了请求(在此示例中为10分钟)