研究HttpSessionListener的问题,请大家积极讨论

viivan 2005-04-19 03:19:10
1。我最近用了HttpSessionListener来监听session,结果发现我做的网页点退出把session注销掉后返回登录页面这是它又会自动生成一个session,这是怎么回事啊?
2。我登录进入系统后浏览了一个网页,退出系统注销session后返回登录页面,发现在浏览器地址栏上打入曾经刚去过的网页还是直接能进去,但再次刷新后又返回登录页面!但我是每个页面都做过session是否存在的判断啊,如果没有session值就自动回到登录页面,为什么前一次登录过的网页明明退出注销了session还能直接进去
3。如果我的HttpSessionListener监听session,我要触发的是session超时后执行一个操作,如修改一个文件或数据库等等。但HttpSessionListener提供的sessionDestroyed是再session被关闭或超时就触发的,有没有只再session超时才触发的方法!
3个问题,是多了点,有没有高手能指点一二,感激不尽

关注中!!!
...全文
1323 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoxhui 2005-04-21
  • 打赏
  • 举报
回复
建议研究一下session的生命期,session已经过期了,你重新登陆当然要重建了,我感觉你把session有点想成application的生命期了
xulz 2005-04-21
  • 打赏
  • 举报
回复
mark
viivan 2005-04-21
  • 打赏
  • 举报
回复
ding
viivan 2005-04-21
  • 打赏
  • 举报
回复
to xiaoxhui 我感觉我对session的概念没搞错啊,只要到登录页面,就算没进入系统,session已经存在了,如果注销后又回到登录页面,session又生成了一个新的,这个新的里面是没有内容的,应该是这样吧?
viivan 2005-04-21
  • 打赏
  • 举报
回复
我的环境是tomcat4.0 ,servlet2.3 ,jdk1.4
在sessionDestroyed事件监听到后运行如下代码
HttpSession userID=event.getSession();
System.out.println("userID: "+userID); //userID有内容,可以输出
String LoginUserID=(String)userID.getAttribute("a_username"); //后面一点内容后没有输出,程序我看了不会有错啊,可能是tomcat和weblogic有区别吧,我这里的getAttribute已经不存在了
if(LoginUserID!=null)
System.out.println("name: "+LoginUserID);
else System.out.println("name: null null null");
jianghuxing 2005-04-21
  • 打赏
  • 举报
回复
呵呵,
viivan 2005-04-21
  • 打赏
  • 举报
回复
myy大哥可能是我对某几个概念没搞清楚,你说的防止重登录的方法我在去看看,有什么不对头的话在发贴,不过我脑子里有自己的几个主意,下午我也试试,反正最后我会把我所有的源码公开给大家看,让以后的朋友碰到类似的问题不会在像我这般苦恼!呵呵
xtuyaowu 2005-04-20
  • 打赏
  • 举报
回复
up
lanwu85 2005-04-20
  • 打赏
  • 举报
回复
学到不少知识
谢了
myy 2005-04-20
  • 打赏
  • 举报
回复
楼主老大,我做的系统已经用了好几年了,关于在线用户监控这部分一直很正常的,
莫非你的环境不一样,我的代码只能在Weblogic中有效??
myy 2005-04-20
  • 打赏
  • 举报
回复
老大,I真服了U !

我给的程序就是在我系统中用的,同样有销毁时打印用户信息的:

/**
捕获会话销毁的事件,把用户的会话从内部全局会话列表中删除掉
*/
public synchronized void sessionDestroyed(HttpSessionEvent se)
{
try
{
//从即将销毁的会话中获取用户名
String LoginUserID=(String)se.getSession().getAttribute("LoginUserID");
。。。
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(DATATIME_FMT);
String ct=df.format(new java.util.Date());
System.out.println("["+ct+"]会话失效,SID = "+se.getSession().getId());
if(LoginUserID!=null)
System.out.println("["+ct+"]登录失效,UID = " + LoginUserID);
}
catch(Exception e)
{
System.err.println("SessionListener.sessionDestroyed: " + e.getMessage());
}
}
}

是能打印出来的,当然了,如果session中根本就没有"LoginUserID"属性的话,
if(LoginUserID!=null) 就不成立了,那就不会打印了,这说明此session产生后,
访问者未登陆。

我的环境: Win2kPro + Weblogic812

------------------------------------------------------------------------
其实没这么简单,因为像你存的HashMap里是sessionID做key,session做值,但是每个用户登录后的用户名相同的时候session的值还是不同的,无法判断!所以要用用户名做值(用户名不可以重复),但是用户名是通过session.getAttribute来得到的,而像你给我的程序是在sessioncreate事件中创造的,这时用户还没进行登录验证,我不知道它的用户名,无法取值!
------------------------------------------------------------------------
你看清楚了,sessioncreate创造事件中,我并没有去访问任何的用户信息的,
不错,就象你说的,“用户还没进行登录验证,我不知道它的用户名”,我只是
简单的把这个刚刚创建的session放入到HashMap中去了,这个HashMap是系统全局的
不会有第二个。之后,在处理用户登录的的页面中可以引用这个HashMap的:

<jsp:useBean id="AllLoginUsers" scope="application" class="java.util.HashMap" />

如果做成“防同一用户重登录”,比如处理user1的登录,就要循环判断了:

HttpSession se=null;
Iterator mi=AllLoginUsers.keySet().iterator();
while(mi.hasNext())
{
sid=(String)mi.next();
se=(HttpSession)AllLoginUsers.get(sid);
if(se!=null)
{
try
{
user=(String)se.getAttribute("LoginUserID");
/*这里写 :
if( "user1".equals(user) )
{
//user1 已经登录了!!!
}
*/
.....
....
viivan 2005-04-20
  • 打赏
  • 举报
回复
突然想问一句:我用attributeAdded事件时发现每set一个attribute都会触发此事件(当然触发,废话:)),但是我只是想在其中一个set的才触发,其它都不触发,有没有办法啊!因为每个都触发都把我的程序运行一遍我可吃不消啊!或者是在attributeAdded有没有判断某个attribute被set的情况
viivan 2005-04-20
  • 打赏
  • 举报
回复
myy朋友,不是我说啊,你说在sessionDestroyed里面,session还没被销毁,sessionDestroyed执行完毕后,这个session才销毁。这话是没错,但是这时候在sessionDestroyed判断,getAttribute("MyFlag"),但是这时候session.getAttribute("MyFlag")应该是得不到的,.....
我还是说这话,因为
public void sessionDestroyed(HttpSessionEvent event) {
String LoginUserID=(String)event.getSession().getAttribute("a_username"); //我的是a_username
System.out.println("name: "+LoginUserID); //这个就打印不出来
}
}
不信你可以试试啊,session。getId()确实还是可以得到,但你前面设的Attribute应该得不到
麻烦myy朋友你了,在细心看一下到底谁有问题
另外你说如果要做成“防同一用户重登录”,也很好办,就是在登录时循环一下HashMap,逐个取出
session,再取session中的用户信息判断一下就可以了。
其实没这么简单,因为像你存的HashMap里是sessionID做key,session做值,但是每个用户登录后的用户名相同的时候session的值还是不同的,无法判断!所以要用用户名做值(用户名不可以重复),但是用户名是通过session.getAttribute来得到的,而像你给我的程序是在sessioncreate事件中创造的,这时用户还没进行登录验证,我不知道它的用户名,无法取值!我想要不把haspmap的创建放在
attributeAdded事件中更好(如果是防止用户重登录的话)
myy 2005-04-20
  • 打赏
  • 举报
回复
另外想问你一下,你的系统是不是禁止用户重登录的,你的HashMap存的是id和session值,如果这个hashmap是防止重登录的,请教一下为什么存session值,不是每个用户进入都会又不同的session值么,存了也没用,不能做重登录比较啊! 如果不是防止重登录的又是用来干吗?
---------------------------------------------
我的系统不防“同一用户重登录”,HashMap存的是id和session,主要是为了便于查看
和监控整个系统中的会话情况,注意,同时包括了只是访问了系统但是并没有登陆
的那些“用户”,他们只有session,但session中并没有任何身份信息。

如果要做成“防同一用户重登录”,也很好办,就是在登录时循环一下HashMap,逐个取出
session,再取session中的用户信息判断一下就可以了。

个人认为“防同一用户重登录”不是很好...
lasthope 2005-04-20
  • 打赏
  • 举报
回复
好文收藏
myy 2005-04-20
  • 打赏
  • 举报
回复
to viivan() 可能你没有理解我说的,我的意思是:

session.setAttribute("MyFlag","是我主动注销的,不是超时的");
session.invalidate();

这两句连在一起写,session.invalidate();执行后,在session真正销毁前,
进入sessionDestroyed,这时候进行判断,如果是超时自然失效的,一定不会
执行上面两句的,而是直接进入sessionDestroyed。
viivan 2005-04-20
  • 打赏
  • 举报
回复
顶一下!!!
viivan 2005-04-20
  • 打赏
  • 举报
回复
另外想问你一下,你的系统是不是禁止用户重登录的,你的HashMap存的是id和session值,如果这个hashmap是防止重登录的,请教一下为什么存session值,不是每个用户进入都会又不同的session值么,存了也没用,不能做重登录比较啊! 如果不是防止重登录的又是用来干吗?
viivan 2005-04-20
  • 打赏
  • 举报
回复
myy 看看我的程序
public void sessionDestroyed(HttpSessionEvent event) {
if(activeSessions > 0)
{

activeSessions--;
System.out.println("HttpSession object has been removed: "+activeSessions);
String Id = event.getSession().getId();
System.out.println("Session Destroyed!Session ID:" + sId);
String LoginUserID=(String)event.getSession().getAttribute("a_username"); //我的是a_username
System.out.println("name: "+LoginUserID); //前面的session都能打印,为什么这个就打印不出来?
}
}
myy 2005-04-20
  • 打赏
  • 举报
回复
public class LesHttpSessionListener implements HttpSessionListener
{
private String DATATIME_FMT="yyyy-MM-dd HH:mm:ss";

public LesHttpSessionListener()
{
//
}
/**
* 捕获会话创建的事件,把包含用户登陆信息的会话存入内部全局会话列表中
*/
public synchronized void sessionCreated(HttpSessionEvent se)
{
try
{
//获取内部全局会话列表
HashMap mon = (HashMap) se.getSession().getServletContext().getAttribute("AllLoginUsers");
if (mon == null)
{
mon=new HashMap(); //全局会话列表不存在就创建之
se.getSession().getServletContext().setAttribute("AllLoginUsers",mon);
}
se.getSession().setMaxInactiveInterval(30);
mon.put(se.getSession().getId(), se.getSession());

java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(DATATIME_FMT);
String ct=df.format(new java.util.Date());
System.out.println("["+ct+"]会话建立,SID = "+se.getSession().getId());
}
catch(Exception e)
{
System.err.println("SessionListener.sessionCreated: " + e.getMessage());
}
}
/**
捕获会话销毁的事件,把用户的会话从内部全局会话列表中删除掉
*/
public synchronized void sessionDestroyed(HttpSessionEvent se)
{
try
{
//从即将销毁的会话中获取用户名
String LoginUserID=(String)se.getSession().getAttribute("LoginUserID");
HashMap mon=(HashMap)se.getSession().getServletContext().getAttribute("AllLoginUsers");
if(mon!=null && mon.containsKey(se.getSession().getId()))
mon.remove(se.getSession().getId()); //把用户的会话从内部全局会话列表中删除掉

java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(DATATIME_FMT);
String ct=df.format(new java.util.Date());
System.out.println("["+ct+"]会话失效,SID = "+se.getSession().getId());
if(LoginUserID!=null)
System.out.println("["+ct+"]登录失效,UID = " + LoginUserID);
}
catch(Exception e)
{
System.err.println("SessionListener.sessionDestroyed: " + e.getMessage());
}
}
}
加载更多回复(11)

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧