2. HttpSessionAttributeListener接口:监听向会话中加入属性、替换属性和删除属性的事件。它有三个方法“
3. HttpSessionBindingListener接口:监听会话与一个属性绑定或解除绑定的事件,它有两个方法:
4. HttpSessionActivationListner接口:监听会话被激活和被搁置的事件,它有两个方法:
对于HttpSessionListener和HttpSessionAttributeListener,它们必须在web.xml文件中通过
下例程的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控制台输出的信息:
这样,我们就知道了监听器的基本使用方法。
许多网站都有统计在线用户人数的功能。当一个用户登入一个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网页的底端显示了在线用户人数。
第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()%>
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,分别输入不同的内容,就会看到在线人数和在线的用户名: