利用session监听器来控制用户的上下线和在线人数问题

Session基于Cookie技术,Session保存在服务器端(一般会设置有效期),SessionID保存在客户端.Session里面保存!!若干个!!!"键-值"对,可以通过 void setAttribute(java.lang.String name, java.lang.Object value) 来修改/添加

HttpSession session = request.getSession();

session.setAttribute("abc",new Integer(567));//新增属性 键:abc 值:new Integer(567)

session.setAttribute("jkl",new Person());//新增属性 键:jkl 值:new Person()

session.setAttribute("abc",new Double(5.67));//已经存在 键abc,将会修改该键对应的值

Session本质上也是一组"键-值"对 其中的"键"保存在客户端(钥匙)是字符串 其中的"值"保存在服务器端(保险箱)可以是Object类型

sessionID与session的关系:钥匙与银行保险箱 钥匙在客户端 保险箱在服务器端

URL重写:解决了关闭浏览器cookie产生的问题

!!!!!!!!!!!!!Session在关闭浏览器时会失效,在下次访问时不能获得同一个Session了

实例:

package chap03;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class GetSession extends HttpServlet

{

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException,IOException

{

response.setContentType("text/html;charset=GBK");

PrintWriter out = response.getWriter();

String user = "";

//此处不新建session,只是去取已经创建的session

HttpSession session = request.getSession(false);

//如果session能够取到,说明用户已经登录

if(session!=null)

{

user = (String)session.getAttribute("abc");

out.println("获得创建的Session");

out.println("<BR>");

out.println("登录名:"+user);

}

//否则,说明用户没有登录,跳转到登录页面让用户登录

else

{

response.sendRedirect("../SessionLogin.htm");

}

}

public void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException,IOException

{

doGet(request,response);

}

}

 

package chap03;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class SaveInfo extends HttpServlet

{

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException,IOException

{

//验证登录者身份,验证过程此处省略

//如果合法用户就产生一个session来放置其登录名

//如果用户输入了用户名,则将其放在session中

if(request.getParameter("userName")!=null)

{

HttpSession session = request.getSession();//没有Session就新建一个

session.setAttribute("abc",

request.getParameter("userName"));//在服务器端存储"键-值对"

}

response.setContentType("text/html;charset=GBK");

PrintWriter out = response.getWriter();

out.println("Session已经创建");

out.println("<BR>");

out.println("转到其他<A HREF=/"chap03.GetSession/">页面</A>");

}

public void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException,IOException

{

doGet(request,response);

}

}

 

******************************************************************************************************************

******************************************************************************************************************

******************************************************************************************************************

servlet 的 session 上下限监听

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;


public class SessionList extends HttpServlet   implements HttpSessionListener {

public void sessionCreated(HttpSessionEvent ex) {
   HttpSession session=ex.getSession();
   //session.setMaxInactiveInterval(10);
   session.getServletContext().setAttribute(session.getId(),session.getId());
  
   System.out.println("用户的id是 ="+session.getId());

}

public void sessionDestroyed(HttpSessionEvent ex) {
   HttpSession session=ex.getSession();
   session.getServletContext().setAttribute(session.getId(),session.getId());  
   System.out.println(session.getId()+"用户下线========");

}

/**
   * Constructor of the object.
   */
public SessionList() {
   super();
}

/**
   * Destruction of the servlet. <br>
   */
public void destroy() {
   super.destroy(); // Just puts "destroy" string in log
   // Put your code here
}


public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

   response.setContentType("text/html");
   PrintWriter out = response.getWriter();
   out
     .println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
   out.println("<HTML>");
   out.println("   <HEAD><TITLE>A Servlet</TITLE></HEAD>");
   out.println("   <BODY>");
   out.print("     This is ");
   out.print(this.getClass());
   out.println(", using the GET method");
   out.println("   </BODY>");
   out.println("</HTML>");
   out.flush();
   out.close();
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        doGet(request,response);
}


public void init() throws ServletException {
   // Put your code here
}

}
//////////////////////////////////////////////////////////////////////////////////////////////////////////

web.xml 加上 这样一句话

 

<listener>
<listener-class>com.SessionList
</listener-class>
</listener>

 

/////////////////////////////////////////////////////////////////////////////////////////////////////

******************************************************************************************************************

******************************************************************************************************************

******************************************************************************************************************

 

捕获Session事件的意义:

1、 记录网站的客户登录日志(登录,退出信息等)

2、 统计在线人数

3、 等等还有很多,呵呵,自己想吧……总之挺重要的。

  Session代表客户的会话过程,客户登录时,往Session中传入一个对象,即可跟踪客户的会话。在Servlet中,传入Session的对象如果是一个实现HttpSessionBindingListener接口的对象(方便起见,此对象称为监听器),则在传入的时候(即调用HttpSession对象的setAttribute方法的时候)和移去的时候(即调用HttpSession对象的removeAttribute方法的时候或Session Time out的时候)Session对象会自动调用监听器的valueBound和valueUnbound方法(这是HttpSessionBindingListener接口中的方法)。由此可知,登录日志也就不难实现了。

  另外一个问题是,如何统计在线人数,这个问题跟实现登录日志稍微有点不同,统计在线人数(及其信息),就是统计现在有多少个Session实例存在,我们可以增加一个计数器(如果想存储更多的信息,可以用一个对象来做计数器,随后给出的实例中,简单起见,用一个整数变量作为计数器),通过在valueBound方法中给计数器加1,valueUnbound方法中计数器减1,即可实现在线人数的统计。当然,这里面要利用到ServletContext的全局特性。(有关ServletContext的叙述请参考Servlet规范),新建一个监听器,并将其实例存入ServletContext的属性中,以保证此监听器实例的唯一性,当客户登录时,先判断ServletContext的这个属性是否为空,如果不为空,证明已经创建,直接将此属性取出放入Session中,计数器加1;如果为空则创建一个新的监听器,并存入ServletContext的属性中。

  举例说明:

  实现一个监听器:

// SessionListener.java

import java.io.*;
import java.util.*;
import javax.servlet.http.*;

//监听登录的整个过程
public class SessionListener implements HttpSessionBindingListener
{

public String privateInfo=""; //生成监听器的初始化参数字符串
private String logString=""; //日志记录字符串
private int count=0; //登录人数计数器

public SessionListener(String info){
this.privateInfo=info;
}

public int getCount(){
return count;
}

public void valueBound(HttpSessionBindingEvent event)
{
count++;
if (privateInfo.equals("count"))
{
return;
}
try{
Calendar calendar=new GregorianCalendar();
System.out.println("LOGIN:"+privateInfo+" TIME:"+calendar.getTime());
logString="/nLOGIN:"+privateInfo+" TIME:"+calendar.getTime()+"/n";
for(int i=1;i< 1000;i++){
File file=new File("yeeyoo.log"+i);
if(!(file.exists()))
file.createNewFile(); //如果文件不存在,创建此文件
if(file.length()>1048576) //如果文件大于1M,重新创建一个文件
continue;
FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true);
//以append方式打开创建文件
foo.write(logString.getBytes(),0,logString.length()); //写入日志字符串
foo.close();
break;//退出
}
}catch(FileNotFoundException e){}
catch(IOException e){}
}

public void valueUnbound(HttpSessionBindingEvent event)
{
count--;
if (privateInfo.equals("count"))
{
return;
}
try{
Calendar calendar=new GregorianCalendar();
System.out.println("LOGOUT:"+privateInfo+" TIME:"+calendar.getTime());
logString="/nLOGOUT:"+privateInfo+" TIME:"+calendar.getTime()+"/n";
for(int i=1;i< 1000;i++){
File file=new File("yeeyoo.log"+i);
if(!(file.exists()))
file.createNewFile(); //如果文件不存在,创建此文件
if(file.length()>1048576) //如果文件大于1M,重新创建一个文件
continue;
FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true);
//以append方式打开创建文件
foo.write(logString.getBytes(),0,logString.length()); //写入日志字符串
foo.close();
break;//退出
}
}catch(FileNotFoundException e){}
catch(IOException e){}
}

}


登录日志的实现:

下面再来看看我们的登录Servlet中使用这个监听器的部分源代码:

……
HttpSession session = req.getSession (true);
……
//////////////////////////////////////////////////////////////////
SessionListener sessionListener=
   new SessionListener("IP:"+req.getRemoteAddr());
//对于每一个会话过程均启动一个监听器
session.setAttribute("listener",sessionListener);
//将监听器植入HttpSession,这将激发监听器调用valueBound方法,
//从而记录日志文件。
//////////////////////////////////////////////////////////////////


当系统退出登录时,只需简单地调用session.removeAttribute(“listener”);

即可自动调用监听器的valueUnbound方法。或者,当Session Time Out的时候也会调用此方法。

登录人数的统计:

ServletContext session1=getServletConfig().getServletContext();
//取得ServletContext对象实例
if((SessionListener)session1.getAttribute("listener1")==null)
{
SessionListener sessionListener1=new SessionListener("count");
//只设置一次,不同于上面日志文件的记录每次会话均设置。
//即当第一个客户连接到服务器时启动一个全局变量,
//此后所有的客户将使用相同的上下文。
session1.setAttribute("listener1",sessionListener1);
//将监听器对象设置成ServletContext的属性,具有全局范围有效性,
//即所有的客户均可以取得它的实例。
}
session.setAttribute("listener1",(SessionListener)session1.
getAttribute("listener1"));
//取出此全局对象,并且将此对象绑定到某个会话中,
//此举将促使监听器调用valueBound,计数器加一。


在此后的程序中随时可以用以下代码取得当前的登录人数:

((SessionListener)session.getAttribute("listener1")).getCount()


getCount()是监听器的一个方法,即取得当前计数器的值也就是登录人数了

你可能感兴趣的:(利用session监听器来控制用户的上下线和在线人数问题)