Tomcat与JavaWeb 5.3 HTTP会话的监听-HttpSessionListener等

在Servlet API中定以了4个用于监听会话中的各种时间的监听器接口。
1.    HttpSessionListener接口:监听创建会话及销毁会话的时间,它有如下两个方法。
  • sessionCreate(HttpSessionEvent event),当容器创建一个会话后,会调用此方法。
  • sessionDestroyed(HttpSessionEvent event),容器销毁一个会话之前,会调用此方法。

2.    HttpSessionAttributeListener接口:监听向会话中加入属性、替换属性和删除属性的事件。它有三个方法“

  • attributeAdded(HttpSessionBindingEvent event):当Web应用向一个会话中加入了一个新的属性,Servlet会调用此方法。
  • attributeRemoved(HttpSessionBindingEvent event)
  • atrributeReplaced(HttpSessionBindingEvent event)

3.    HttpSessionBindingListener接口:监听会话与一个属性绑定或解除绑定的事件,它有两个方法:

  • valueBound(HttpSessionBindingEvent event):当Web应用把一个属性与会话绑定后,Servlet容器会调用此方法。
  • valueUnbound(HttpSessionBindingEvent event)

4.    HttpSessionActivationListner接口:监听会话被激活和被搁置的事件,它有两个方法:

  • sessionDidActivate(HttpSessionEvent event):当Servlet容器激活一个会话后,会调用此方法。
  • sessionWillPassivate(HttpSessionEvent event):当Servlet容器搁置一个会话之前,会调用此方法。

对于HttpSessionListener和HttpSessionAttributeListener,它们必须在web.xml文件中通过元素向Servlet容器注册。对于HttpSessionBindingListener和HttpSessionActivationListener,它们由会话的属性来实现。例如假定MyData类的对象会作为会话的属性与会话绑定,如果希望监听MyData对象与会话绑定、解除绑定以及会话被搁置或激活的事件,那么可以让MyData类实现HttpSessionBindingListener和HttpSessionActivationListener接口。

下例程的MyData类表示与会话绑定的某种数据,实现了HttpSessionBindingListener和HttpSessionActivationListener接口。

MyData.java(用IDEA进行开发的话,需要在src文件夹下新建一个package-- mypack,将MyData放在该package里)

package mypack;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;

public class MyData implements HttpSessionActivationListener,HttpSessionBindingListener ,Serializable{
    private  int data;
    public MyData(){}
    public MyData(int data){
        this.data = data;
    }
    public int getData(){
        return data;
    }
    public void setData(){
        this.data = data;
    }
    public void valueBound(HttpSessionBindingEvent event){
        System.out.println("MyData is bound with a session.");
    }
    public void valueUnbound(HttpSessionBindingEvent event){
        System.out.println("MyData is unbound with a session.");
    }
    public void sessionDidActivate(HttpSessionEvent event){
        System.out.println("A session is activate.");
    }
    public void sessionWillPassivate(HttpSessionEvent event){
        System.out.println("A session will be passivate.");
    }
}

MySessionLifeListener类实现了HttpSessionListener和HttpSessionAttributeListener接口。

MySessionLifeListener.java

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MySessionLifeListener implements HttpSessionAttributeListener,HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("A new session is created.");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("A new session is to be destroyed.");
    }

    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("Attribute("+se.getName()+"/"+se.getValue()+") is added into a session.");
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("Attribute("+se.getName()+"/"+se.getValue()+") is removed from a session.");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("Attribute("+se.getName()+"/"+se.getValue()+") is replaced in a session.");
    }
}
在web.xml文件中只需配置MySessionLifeListener类,不需要配置MyData类。

    
        MySessionLifeListener
    
例程 sessionopt.jsp访问会话,并产生创建会话、销毁会话、向会话中添加/删除/替换属性、会话与属性绑定/解绑等事件。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="mypack.MyData" %>
<%  String action = request.getParameter("action");
    if (action==null){
%>
加入属性
结束会话 <% }else if (action.equals("invalidate")){ session.invalidate(); %> 开始新的会话
<% }else if (action.equals("add")){ session.setAttribute("data",new MyData(1)); %> 替换属性
删除属性
结束会话
<% }else if (action.equals("remove")){ session.removeAttribute("data"); %> 加入属性
结束会话
<% }else if (action.equals("replace")){ session.setAttribute("data",new MyData(1)); %> 删除属性
结束会话
<%}%>

运行应用,访问localhost:8080/sessionopt.jsp,一边点击对属性和会话进行操作的超链接,一边注意观察Tomcat控制台输出的信息:
Tomcat与JavaWeb 5.3 HTTP会话的监听-HttpSessionListener等_第1张图片

这样,我们就知道了监听器的基本使用方法。

1.    用HttpSessionListener统计在线用户人数

许多网站都有统计在线用户人数的功能。当一个用户登入一个Web应用时,就会开始一个会话,当这个会话被销毁,就意味着永辉离开了Web应用。因此,对于多数Web应用,一个在线用户对应一个会话,Web应用的当前的所有会话数目就等于在线用户的数目。

我们以之前简单的邮件应用做例子,新版的邮件应用提供了统计在线用户的功能。OnlineCounterListener类实现了HttpSessionListener接口,OnlineCounterListener把在线用户人数作为counter属性存放在Web应用范围内。当容器创建一个会话时,OnlineCounterListener就会把Web应用范围内的counter属性的值加1,销毁时则减1.

OnlineCounterListener.java

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnlineCounterListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        ServletContext context = session.getServletContext();
        Integer counter = (Integer)context.getAttribute("counter");
        if (counter==null){
            counter = 1;
        }else {
            counter++;
        }
        context.setAttribute("counter",counter);
        //处于演示范例的需要,把会话的过期时间设定为60s
        session.setMaxInactiveInterval(60);
        System.out.println("A new session is created.");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        ServletContext context = session.getServletContext();
        Integer counter = (Integer) context.getAttribute("counter");
        if (counter == null) {
            return;
        } else {
            counter --;
        }
        context.setAttribute("counter",counter);
        System.out.println("A new session is to be destroyed.");
    }
}
在web.xml文件中对该类做配置:

    
        OnlineCounterListener
    
在mailcheck.jsp的末尾增加显示在线人数的代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    mailCheckPage


<%
    String name = null;
    name=request.getParameter("username");
    if (name!=null){
        session.setAttribute("username",name);
    }else {
        name = (String)session.getAttribute("usernae");
        if (name==null){
            response.encodeRedirectURL("maillogin.jsp");
        }
    }
%>
">登录   
">注销   

当前用户为<%=name%>

你的信箱中有10封邮件

<% //从Web应用范围内获取表示在线用户人数的counter属性 Integer counter = (Integer)application.getAttribute("counter"); if (counter!=null){ %> 当前在线人数为:<%=counter%>
<% }%>

运行Web应用,打开多个浏览器分别访问localhost:8080/login.jsp,登录后会看到mailcheck.jsp网页的底端显示了在线用户人数。
Tomcat与JavaWeb 5.3 HTTP会话的监听-HttpSessionListener等_第2张图片

2.    用HttpSessionBindingListener统计在线人数

第1节的OnlineCounterListener实际上统计的是Web应用的当前的所有会话的书目,它无法统计所有在线用户的具体名单。本节介绍的HttpSessionBindingListener还可以统计所有在线用户的名单。涉及到的文件源码分别如下:

(在mypack中)User.java

package mypack;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class User implements HttpSessionBindingListener {
    private OnlineUsers onlineUsers = OnlineUsers.getInstance();
    private String name = null;

    public User(String name){
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    public void valueBound(HttpSessionBindingEvent event) {
        onlineUsers.add(name);
        System.out.println(name+ " is bound with a session.");
    }
    public void valueUnbound(HttpSessionBindingEvent event) {
        onlineUsers.remove(name);
        System.out.println(name + " is unbound with a session.");
    }
}
(mypack中)OnlineUsers.java
package mypack;

import java.util.ArrayList;
import java.util.List;

public class OnlineUsers {
    private static final OnlineUsers onlineUsers = new OnlineUsers();//唯一的OnlineUsers实例
    private List users = new ArrayList();  //存放在线用户名
    public void add(String name){
        users.add(name);
    }

    public void remove(String name) {
        users.remove(name);
    }

    public List getUsers() {
        return users;
    }

    public int getCount() {
        return users.size();
    }

    public static OnlineUsers getInstance() {
        return onlineUsers; //返回唯一的OnlineUsers实例
    }
}
maillogin.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page import="mypack.*" %>


    mailLoginPage


<%
    String name="";
    User user = null;
    if (!session.isNew()){
        //name=(String)session.getAttribute("username");
        user = (User)session.getAttribute("user");
        if (user==null)name="";
        else
            name = user.getName();
    }
%>

欢迎光临邮件系统

Session ID:<%=session.getId()%>

">
User Name: 
 
mailcheck.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="mypack.*" %>
<%@ page import="java.util.List" %>


    mailCheckPage


<%
    String name = null;
    User user= null;
    name=request.getParameter("username");
    if (name!=null){
        session.setAttribute("user",new User(name));
    }else {
        user = (User)session.getAttribute("user");
        if (name==null){
            response.sendRedirect(response.encodeRedirectURL("maillogin.jsp"));
        }
    }
%>
">登录   
">注销   

当前用户为<%=name%>

你的信箱中有10封邮件

<% OnlineUsers onlineUsers = OnlineUsers.getInstance(); List users = onlineUsers.getUsers(); %>
当前在线人数为:<%=onlineUsers.getCount()%>
<%for (int i =0;i <%=users.get(i)%>    <%}%>
maillogout.jsp
<%@ page import="mypack.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    mailLogoutPage


<%
    User user = (User)session.getAttribute("user");
    String name=null;
    if (user!=null) name=user.getName();
    session.invalidate();
%>
<%=name%>,再见!

" >重新登录邮件系统   

运行Web应用,打开多个浏览器访问localhost:8080/maillogin.jsp,分别输入不同的内容,就会看到在线人数和在线的用户名:
Tomcat与JavaWeb 5.3 HTTP会话的监听-HttpSessionListener等_第3张图片

你可能感兴趣的:(Tomcat&JavaWeb)