在Servlet技术中已经定义了一些事件,并且可以针对这些事件来编写相关的事件监听器,从而对事件做出相应处理。例如,想要在Web应用程序启动和关闭时执行一些任务(如数据库连接的建立和释放),或者想要监听Session的创建和销毁,那么就可以通过监听器来实现。
1、Servlet监听器简介
监听器的作用是监听Web容器的有效期事件,因此它是由容器管理的。利用Listener接口监听在容器中的某个执行程序,并且根据其应用程序的需求做出适当的响应。下表列出了Servlet中的9个Listener接口和7个Event类。
Listener接口与Event类:
Listener接口 | Event类 |
---|---|
ServletContextListener | ServletContextEvent |
ServletContextAttributeListener | ServletContextAttributeEvent |
HttpSessionListener | HttpSessionEvent |
HttpSessionActivationListener | |
HttpSessionAttributeListener | HttpSessionBindingEvent |
HttpSessionBindingListener | |
ServletRequestListener | ServletRequestEvent |
ServletRequestAttributeListener | ServletRequestAttributeEvent |
AsyncListener | AsyncEvent |
2、Servlet监听器的原理
Servlet监听器是当今Web应用开发的一个重要组成部分。它是在Servlet2.3规范中和Servlet过滤器一起引入的,并且在Servlet 2.4规范中对其进行了较大的改进,主要就是用来对Web应用进行监听和控制的,极大地增强了Web应用的事件处理能力。
Servlet监听器的功能比较接近Java的GUI程序的监听器,可以监听由于Web应用中状态改变而引起的Servlet容器产生的相应事件,然后接受并处理这些事件。
3、Servlet上下文监听
Servlet上下文监听可以监听ServletContext对象的创建、删除以及属性添加、删除和修改操作,该监听器需要用到如下两个接口。
3.1 ServletContextListener接口
该接口存放在 javax.servlet 包内,它主要实现监听ServletContext的创建和删除。ServletContextListener接口提供了两个方法,它们也被称为“Web应用程序的生命周期方法”。
contextInitialized(ServletContextEvent sce)方法:通知正在收听的对象,应用程序已经被加载及初始化。
contextDestroyed(ServletContextEvent sce)方法:通知正在收听的对象,应用程序已经被载出,即关闭。
示例:创建ServletContextListener接口的监听器。
package com.pjb.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
public class MyContextListener implements ServletContextListener
{
public MyContextListener()
{
// TODO Auto-generated constructor stub
}
public void contextInitialized(ServletContextEvent sce)
{
// TODO Auto-generated method stub
}
public void contextDestroyed(ServletContextEvent sce)
{
// TODO Auto-generated method stub
}
}
要让Web容器在Web应用程序启动时通知MyContextListener,需要在 web.xml 文件中使用<listener>元素来配置监听器类。对于本示例,在 web.xml 文件中需要进行配置。
<listener>
<listener-class>com.pjb.listener.MyContextListener</listener-class>
</listener>
3.2 ServletContextAttributeListener接口
该接口存放在 javax.servlet 包内,主要实现监听ServletContext属性的增加、删除和修改。ServletContextAttributeListener接口提供了以下3个方法。
attributeAdded(ServletContextAttributeEvent event)方法:当有对象加入ServletContext对象的范围时,通知正在收听的对象。
attributeReplaced(ServletContextAttributeEvent event)方法:当有ServletContext对象的范围取代另一个对象时,通知正在收听的对象。
attributeRemoved(ServletContextAttributeEvent event)方法:当有ServletContext对象的范围移除时,通知正在收听的对象。
4、HTTP会话监听
HTTP会话监听(HttpSession)信息,有4个接口可以进行监听。
4.1 HttpSessionListener接口
HttpSessionListener接口实现监听HTTP会话的创建、销毁。HttpSessionListener接口提供了以下两个方法。
sessionCreated(HttpSessionEvent se)方法:通知正在收听的对象,session已经被加载及初始化。
sessionDestroyed(HttpSessionEvent se)方法:通知正在收听的对象,session已经被销毁。(HttpSessionEvent 类的主要方法是getSession(),可以使用该方法回传一个session对象)。
4.2 HttpSessionActivationListener接口
HttpSessionActivationListener接口实现监听HTTP会话active和passivate。HttpSessionActivationListener接口提供了以下两个方法。
sessionDidActivate(HttpSessionEvent se)方法:通知正在收听的对象,它的session已经变为有效状态。
sessionWillPassivate(HttpSessionEvent se)方法:通知正在收听的对象,它的session已经变为无效状态。
4.3 HttpSessionAttributeListener接口
HttpSessionAttributeListener接口实现监听HTTP会话中属性的设置请求。HttpSessionAttributeListener接口提供了3个方法。
attributeAdded(HttpSessionBindingEvent event)方法:当有对象加入session的范围时,通知正在收听的对象。
attributeReplaced(HttpSessionBindingEvent event)方法:当在session的范围有对象取代另一个对象时,通知正在收听的对象。
attributeRemoved(HttpSessionBindingEvent event)方法:当有对象从session的范围移除时,通知正在收听的对象。(HttpSessionBindingEvent类主要有3个方法:getName() 、getSession() 、getValue())。
4.4 HttpSessionBindingListener接口
HttpSessionBindingListener接口实现监听HTTP会话中对象的绑定信息,它是唯一不需要再 web.xml 文件中设定Listener的。HttpSessionBindingListener接口提供了以下两个方法。
valueBound(HttpSessionBindingEvent event)方法:当有对象加入session的范围时会被自动调用。
valueUnbound(HttpSessionBindingEvent event)方法:当有对象从session的范围内移除时会被自动调用。
5、Servlet请求监听
在Servlet 2.4规范中,新增加了一个技术,就是可以监听客户端的请求。一旦能够在监听程序中获取客户端的请求,就可以对请求进行统一处理。要实现客户端的请求和请求参数设置的监听需要实现两个接口。
5.1 ServletRequestListener接口
ServletRequestListener接口提供了以下两个方法。
requestInitialized(ServletRequestEvent sre)方法:通知正在收听的对象,ServletRequest已经被加载及初始化。
requestDestroyed(ServletRequestEvent sre)方法:通知正在收听的对象,ServletRequest已经被载出,即关闭。
5.2 ServletRequestAttributeListener接口
ServletRequestAttributeListener接口提供了以下3个方法。
attributeAdded(ServletRequestAttributeEvent srae)方法:当有对象加入request的范围时,通知正在收听的对象。
attributeReplaced(ServletRequestAttributeEvent srae)方法:当在request的范围内有对象取代另一个对象时,通知正在收听的对象。
attributeRemoved(ServletRequestAttributeEvent srae)方法:当有对象从request的范围移除时,通知正在收听的对象。
6、AsyncListener异步监听
Servlet 3.0为异步处理提供了一个监听器,使用AsyncListener接口表示。此接口负责管理异步事件,AsyncListener接口提供了4个方法。
onStartAsync(AsyncEvent event)方法:当异步线程开始时,通知正在收听的对象。
onError(AsyncEvent event)方法:当异步线程出错时,通知正在收听的对象。
onTimeout(AsyncEvent event)方法:当异步线程执行超时,通知正在收听的对象。
onComplete(AsyncEvent event)方法:当异步执行完毕时,通知正在收听的对象。
7、Servlet监听器统计在线人数
监听器的作用是监听Web容器的有效事件,它由Servlet容器管理,利用Listener接口监听某个执行程序,并根据该程序的需求做出适当的响应。下面介绍一个应用Servlet监听器实现统计在线人数的实例。
示例:应用Servlet监听器统计在线人数。
(1)创建UserInfoList类文件,主要是用来存储在线用户和对在线用户进行具体操作。
package com.pjb.listener;
import java.util.Vector;
/**
* 用户信息实体类
*
* @author pan_junbiao
*
*/
public class UserInfoList
{
private static UserInfoList user = new UserInfoList();
private Vector vector = null;
public UserInfoList()
{
this.vector = new Vector();
}
/* 外界使用的instance对象 */
public static UserInfoList getInstance()
{
return user;
}
/* 增加用户 */
public boolean addUserInfo(String user)
{
if (user != null)
{
this.vector.add(user);
return true;
} else
{
return false;
}
}
/* 获取用户列表 */
public Vector getList()
{
return vector;
}
/* 移除用户 */
public void removeUserInfo(String user)
{
if (user != null)
{
vector.removeElement(user);
}
}
}
(2)创建UserInfoTrace类文件,主要实现HttpSessionBindingListener接口。HttpSessionBindingListener接口实现监听HTTP会话中对象的绑定信息,它是唯一不需要再 web.xml 文件中设定Listener的。
package com.pjb.listener;
import javax.servlet.http.HttpSessionBindingEvent;
/**
* 用户信息监听器
*
* @author pan_junbiao
*
*/
public class UserInfoTrace implements javax.servlet.http.HttpSessionBindingListener
{
private String user;
private UserInfoList container = UserInfoList.getInstance();
public UserInfoTrace()
{
user = "";
}
public void setUser(String user)
{
this.user = user;
}
public String getUser()
{
return this.user;
}
public void valueBound(HttpSessionBindingEvent arg0)
{
System.out.println("上线" + this.user);
}
public void valueUnbound(HttpSessionBindingEvent arg0)
{
System.out.println("下线" + this.user);
if (user != "")
{
container.removeUserInfo(user);
}
}
}
(3)创建login.jsp登录页面。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用监听查看在线用户</title>
<script language="javascript">
function checkEmpty(form)
{
for(i=0;i<form.length;i++)
{
if(form.elements[i].value=="")
{
alert("表单信息不能为空");
return false;
}
}
}
</script>
</head>
<body>
<form name="form" method="post" action="showUser.jsp" onSubmit="return checkEmpty(form)">
用户名:<input type="text" name="user"><br><br>
<input type="submit" name="Submit" value="登录">
</form>
</body>
</html>
(4)创建showUser.jsp显示页面,在页面中设置session的setMaxInactiveInterval()方法值为10秒,这样可以缩短session的生命周期。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<%@ page import="com.pjb.listener.*"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>使用监听查看在线用户</title>
</head>
<%
UserInfoList list=UserInfoList.getInstance();
UserInfoTrace ut=new UserInfoTrace();
String name=request.getParameter("user");
ut.setUser(name);
session.setAttribute("list",ut);
list.addUserInfo(ut.getUser());
session.setMaxInactiveInterval(10);
%>
<body>
<h3>当前在线用户:</h3>
<textarea rows="4" cols="20">
<%
Vector vector=list.getList();
if(vector!=null&&vector.size()>0){
for(int i=0;i<vector.size();i++){
out.println(vector.elementAt(i));
}
}
%>
</textarea><br>
<a href="login.jsp" target="_blank" rel="external nofollow" >返回</a>
</body>
</html>
执行结果:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL2Z0VhlWNXRWc5wmYoJ0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4QzNyIjMwgTMxEzMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
当用户输入用户名,点击“登录”后,会进入到在线人数界面。
8、Servlet3.0新特性:@WebListener注释
在Servlet3.0中新增了@WebListener注释,使用该注释就不需要在 web.xml 文件中配置<listener>标签了。
@WebListener注释用于声明监听器,该注释用于充当给定web应用上下文中各种web应用事件的监听器的类。可以使用@WebListener来标注一个实现:ServletContextListener、ServletContextAttributeListener、ServletRequestListener、ServletRequestAttributeListener、HttpSessionListener、HttpSessionAttributeListener的类。@WebListener注释有一个value的属性,该属性为可选属性,用于描述监听器信息。
示例:使用@WebListener注释,创建监听器。
@WebListener("监听器的描述信息")
public class MyContextListener implements ServletContextListener
{
// 省略了监听器中间的代码
}
这样配置完成后,就不必在 web.xml 文件中配置相应的<listener>元素了。与上面的代码等价的 web.xml 文件的配置如下:
<listener>
<listener-class>MyContextListener</listener-class>
</listener>