是否有可能“拦截”会话超时?
我尝试了HttpSessionListener
,但据我所知,当调用HttpSessionListener.sessionDestroyed()`方法时,Session已被销毁。 (所以我没有机会确定用户,拥有超时的会话)
另一个选项是PhaseListener,检查在RestoreView-Phase中Session是否为“new”。
但是我需要执行一些动作“第二次”会话超时 - 不再在以后的任何刷新,而不是将来的任何登录。
(背景:需要从某些对象中删除锁,用户可能在运行超时时一直在处理。)
有没有办法实现这个目标?
编辑: 尝试1:在问题的SessionBeans上使用@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());
}
}
预期结果:仍然可以访问Session bean。
结果:'ContextNotActiveException':
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并在所有Session Scoped bean旁边创建了SessionMap中的手动条目:FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user_id", 5)
。
可以在SessionListener中访问此值,并允许我关闭给定用户的所有锁。
答案 0 :(得分:1)
我尝试了HttpSessionListener,但据我所知,当调用HttpSessionListener.sessionDestroyed()`方法时,Session已被销毁。 (所以我没有机会确定用户,拥有超时的会话)
我不确定这是如何形成问题的。您仍然可以通过HttpSession
参数获取具体的HttpSessionEvent
实例,您可以在其中调用getAttribute()
方法,以便检查已登录的用户,以防它存储为会话属性。
User user = (User) event.getSession().getAttribute("user");
// ...
更新:根据您失败的尝试:
不确定为什么不调用@PreDestroy
。这将是CDI实施的具体问题。它至少与JSF / Servlet无关。
您不应该抓取注入的@Named
实例。您应该直接将具体实例作为会话属性。在具体的托管bean名称上使用HttpSession#getAttribute()
。
您在每次迭代期间重新创建迭代器。您应该创建一次并在每次迭代期间重复使用它。将getAttributeNames()
放在while
之外。这个问题与JSF / Servlet无关,只是基本的Java。
答案 1 :(得分:1)
我这样做的方法是将UserBean本身设为HttpSessionListener
。然后它仍然具有所有自己的状态,因此它知道它是谁“,无论会话是否仍然具有调用回调时的属性。