sessionDestroyed执行时间的奇怪问题

问题描述:

用户登陆后转到list.jsp页面,此页面不停向服务器请求数据。用户的登录名保存到session和servletContext的用户列表中一个list。当用户session失效的时候从用户列表中删除用户。

问题是:

虽然不停向服务器发送数据,但还是会在不到一分钟的时间内调用sessionDestroyed方法,难道此方法不是在session失效的时候才被调用?

 

下面贴出完整代码。

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>login</title>
</head>
<body style="text-align: center;">

	<p style="margin-top: 200px;" />
	<p>${error }</p>
	<form action="login" method="post">
		用户名:<input type="text" name="name"/>
		<p/>
		<input type="submit"/>
	</form>
</body>
</html>

 

 LoginServlet

public class LoginServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		String name = req.getParameter("name");
		List<String> list;
		if(name==null||name.equals("")){
			req.setAttribute("error", "登录名不能为空!");
			req.getRequestDispatcher("login.jsp").forward(req, resp);
			return;
		}
		//从ServletContext中取得已登录用户信息的容器,一个list
		Object o = getServletContext().getAttribute("list");
		if(o==null){
			//如果没有,则创建一个并放入ServletContext
			list = new ArrayList();
			getServletContext().setAttribute("list", list);
		}
		else {
			//有则返回
			list = (List<String>)o ;
		}
		//如果当前登陆用户有重名的则,无法登陆
		if(list.contains(name)){
			req.setAttribute("error", "用户已存在!");
			req.getRequestDispatcher("login.jsp").forward(req, resp);
			return;
		}
		//将登陆用户放入ServletContext中的list
		list.add(name);
		getServletContext().setAttribute("list", list);
		//将当前用户的用户名放入session
		HttpSession session = req.getSession();
		Logger.getLogger(this.getClass().getName()).info("原始会话超时时间为:"+session.getMaxInactiveInterval());
		session.setMaxInactiveInterval(5); //设置当前会话的失效时间,单位是秒。即5秒不回应则判定离线
		session.setAttribute("name", name);
		Logger.getLogger(this.getClass().getName()).info("设定会话超时时间为:"+session.getMaxInactiveInterval());
		
		req.setAttribute("list", list);

		req.getRequestDispatcher("list.jsp").forward(req, resp);
		
	}
}

 list.jsp ,用到了jquery进行Ajax调用

  

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>login</title>
<style type="text/css">
	.left{
		width: 200px;
		height: 600px;
		float: left;
		border: dashed 1px black;
	}
	.right{
		width: 600px;
		height: 600px;	
		margin-left: 220px;
		border: dotted 1px black;
		overflow: scroll;
	}
</style>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript">
	//如果返回类型定义为json,则无法重复执行,所以只能自己eval了。原因是jquery1.4解析json格式比较严格,这里返回的是不严格的json格式,致使解析失败。解决方法:1.返回严格的json格式数据2.自己eval生成json对象
	$(function(){
		function getText(){
			$.post("control",function(data){
				var json = eval("("+data+")");
				//返回在线用户数组
				var list = json.list;
				var date = json.date; //服务器端返回的日期
				var $left = $(".left");
				var nameList = "";  //构造用户在线字符串形式,方便添加进html
				for(var i in list){
					nameList = nameList+"<li>"+list[i]+"</li>"
				}
				$left.empty().html("当前用户列表:<br/><ul>"+nameList+"</ul>");
				$(".right").append("服务器端传来数据:"+date+'<br/>');
				//继续请求服务器
				getText();
			});
		}
		//开始执行
		getText();
	});
</script>
</head>
<body>
<div class="left">
当前用户列表:
<p></p>
<ul>
	<%
		List<String> list = (List<String>)request.getAttribute("list");
		for(String s:list){
	%>
		<li><%=s %></li>
		<%} %>
</ul>
</div>
<div class="right">

</div>
</body>
</html>

   ControlServlet

 

public class ControlServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String text;
		List<String> list;
		StringBuilder sb = new StringBuilder();
		text = simpleDateFormat.format(new Date());
		//取得在线的列表
		Object o =getServletContext().getAttribute("list");
		if(o==null) list = null;
		else list = (List<String>)o;
		
		//构造返回的String, json格式
		sb.append("{list:[");
		if(list==null){
			//一个空的数组
			sb.append("],");
		}else{
			for(int i=0;i<list.size();i++){
				sb.append("\"");
				sb.append(list.get(i));
				sb.append("\"");
				//如果是最后一个则不添加 ','
				if(i!=list.size()-1) sb.append(",");
			}
			sb.append("],");
		}
		//把服务器返回的时间添加入json
		sb.append("date:").append("\"").append(text).append("\"");
		sb.append("}");
		
		resp.setCharacterEncoding("UTF-8");
		PrintWriter out = resp.getWriter();
		//停留一秒后,然后再向客户端输出。如果不停留,则浏览器会不停处理,可能崩溃。
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			//
		}
		//返回组装好的json字符串形式
		out.print(sb.toString());
		//Logger.getLogger(this.getClass().getName()).info("服务器段返回json的字符串为:\n"+sb.toString());
	}

}

 

SessionListener

public class SessionListening implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent se) {
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		//从session中取得登陆的用户名
		Object o = se.getSession().getAttribute("name");
		//如果未登录则返回
		if(o==null) return;
		String name = (String)o;
		//从ServletContext中获得登陆用户的容器
		Object ob = se.getSession().getServletContext().getAttribute("list");
		//如果容器为null,则返回
		if(ob==null) return;
		List<String> list = (List<String>)ob;
		//从list中移除当前用户
		if(list.contains(name)) list.remove(name);
		//把改变后的list重新放入ServletContext
		se.getSession().getServletContext().setAttribute("list", list);
		Logger.getLogger("session").info("用户"+name+",退出!");
		
	}

}

 

web.xml

  <listener>
  		<listener-class>test.servlet.SessionListening</listener-class>
  </listener>
  
  <servlet>
  		<servlet-name>login</servlet-name>
  		<servlet-class>test.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  		<servlet-name>login</servlet-name>
  		<url-pattern>/login</url-pattern>
  </servlet-mapping>
  <servlet>
  		<servlet-name>control</servlet-name>
  		<servlet-class>test.servlet.ControlServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  		<servlet-name>control</servlet-name>
  		<url-pattern>/control</url-pattern>
  </servlet-mapping>

 

虽然设置session的失效时间在5秒,但是总是在大概1分钟的时候调用sessionDestroyed方法。

以上为全部工程文件,

等待高手解答

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值