servlet监听器
Servlet监听器也叫做 listener,通过它可以监听Web应用的上下文(环境)信息、Servlet请求信息、Servlet会话信息,并自动根据不同情况,在后台调用相 应的处理程序。通过监听器,可以自动激发一些操作,比如监听在线人数,当增加一个HttpSession时就激发 sessionCreated(HttpSessionEvent)方法,这样就可以给在线人数加1。
监听器原理
Servlet监听器是Web应用开发的一个重要组成部 分,Servlet监听器是在Servlet2.3规范中和Servlet过滤器一起引入的。在 Servlet2.4 规范中对其进行了比较大的改进。主要就是用来对Web应用进行监督和控制,极大地增强了Web应用的事件处理能力。
监听器的类型
在 Servlet 2.4 规范中,根据监听对象的类型和范围,将监听器分为3类:ServletRequest监听器(请求监听器)、HttpSession监听器(会话监听器)、ServletContext监听器(上下文监听器),其中请求监听器(ServletRequest监听器)是 Servlet 2.4 规范中新增加的监听器,可以用来监听客户的端请求,在Servlet 2.4 规范中包含了8个监听器接口和6个监听器事件类,具体的监听器接口和事件如下表:
1.被监听对象ServletContext
对ServletContext对象(JSP页面中称为application对象)实现监听涉及2个接口:
(1)ServletContextListener接口:用于监听ServletContext对象的创建和删除:接口中定义的回调方法有:
当创建一个ServletContext对象时,激发 contextInitialzed(ServletContextEvent)方法。
当撤消一个ServletContext对象时,激发 contextDestroyed(ServletContextEvent)方法。
(2)ServletContextAttributeListener接口:用于监听ServletContext对象的属性操作。接口中定义的回调方法有:
增加属性时,激发 attributeAdded(ServletContextAttributeEvent)
删除属性时,激发 attributeRemoved(ServletContextAttributeEvent)
修改属性时,激发 attributeReplaced(ServletContextAttributeEvent)
2.被监听对象HttpSession
对HttpSession对象(session)实现监听涉及4个接口:
(1)HttpSessionListener接口:这个接口监听Http会话的创建和撤消,并在某个session对象建立和销毁之前调用某个方法。接口中定义的回调方法有:
创建一个session对象时,激发 sessionCreated(HttpSessionEvent)
删除一个session对象时,激发 sessionDestroyed(HttpSessionEvent)
(2)HttpSessionActivationListener接口:监听Http会话的active和passivate状态。接口中定义的回调方法有:
session对象被保存到磁盘时,激发 sessionWillPassivate(HttpSessionEvent)
session对象被调入内存时,激发 sessionDidActivate(HttpSessionEvent)
Activate与Passivate是用于置换session对象的动作,当Web服务器因为资源利用或负载平衡等原因要将内存中的 session对象暂时储存至硬盘或其它储存器时(通过对象序列化),所作的动作称之为Passivate,而硬盘或储存器上的session对象重新加 载到JVM中时所采的动作称之为Activate。sessionDidActivate()方法与 sessionWillPassivate()方法分别于Activeate后与Passivate前被调用。
(3)HttpSessionAttributeListener接口:监听Http会话中属性的设置信息。接口中定义的回调方法有:
向某个session对象中增加新属性时,激发 attributeAdded(HttpSessionBindingEvent)
删除某个session对象中的属性时,激发 attributeRemoved(HttpSessionBindingEvent)
修改某个session对象中的属性时,激发 attributeReplaced(HttpSessionBindingEvent)
使用HttpSessionBindingEvent事件类对象的getSession()方法可以得到这个session对象,使用 HttpSessionBindingEvent对象的getName()方法得到属性的名字,使用getValue()方法得到属性的值。
若有属性加入到某个会话(HttpSession)对象,则会调用attributeAdded(),同理在替换属性与移除属性时,会分别调用attributeReplaced()、attributeRemoved()。
(4)HttpSessionBindingListener接口:这是唯一一个不需要在web.xml中进行配置的监听器接口,监听Http会话中属性的变化情况。接口中定义的回调方法有:
属性被加入到session中时,激发属性的 valueBound(HttpSessionBindingEvent)
属性被从session中删除时,激发属性的 valueUnbound(HttpSessionBindingEvent)
使用HttpSessionBindingEvent事件类对象的getSession()方法可以得到这个session对象,使用 HttpSessionBindingEvent对象的getName()方法得到属性的名字,使用getValue()方法得到属性的值。
如果一个对象object实现了HttpSessionBindingListener接口时,当把object对象保存到session中时, 就会自动调用object对象的valueBound()方法,如果对象object被从session(HttpSession)移除时,则会调用 object对象的valueUnbound()方法。使用这个接口,可以让一个对象自己知道它自己是被保存到了session中,还是从session 中被删除了。
3.被监听对象ServletRequest
对ServletRequest对象(request)实现监听涉及2个接口:
(1)ServletRequestListener接口:监听请求的创建和撤消,该接口用来监听请求到达和结束,因此可以在请求达到前和请求结束前执行一些用户行为。 接口中定义的回调方法有:
请求对象初始化时,激发 requestInitialized(ServletRequestEvent)
请求对象被撤消时,激发 requestDestroyed(ServletRequestEvent)
在request(HttpServletRequest)对象建立或被消灭时,会分别调用requestInitialized()和requestDestroyed()方法。
(2)ServletRequestAttributeListener接口:监听请求中(request对象中)的属性变化。接口中定义的回调方法有:
向某个request对象中增加属性时被调用attributeAdded(ServletRequestAttributeEvent)方法。
从某个request对象中删除属性时被调用attributeRemoved(ServletRequestAttributeEvent)方法。
修改某个request中的属性时被调用attributeReplaced(ServletRequestAttributeEvent)方法。
使用ServletRequestEvent类的getServletRequest()方法可以得到这个被监听的请求对象,使用 ServletRequestAttributeEvent类的getName()方法可以得到属性名,getValue()方法可以得到属性的值。
若有属性加入到某个request对象中时则会调用attributeAdded(),同理在替换属性与删除属性时,会分别调用attributeReplaced()、 attributeRemoved()。
当Web应用程序启动后,在处理任何请求之前,调用contextInitialzed()方法和getInitParamter()方法,返回 在配置文件中为定义的环境初始化信息。不同的组件,如Servlet、JSP、监听器和过滤器等,通过ServletRequest、 HttpSession 和 ServletContext达到数据共享,这些类都提供了下面的一组方法,可以使用这组方法来设置、获取、删除属性:
public void setAttribute("属性名",属性值);
public Object getAttribute("属性名");
public void removeAttribute("属性名");
监听器实例
在OnLineListener类中,每增加一个session对象,人数加1,每撤消一个session对象,人数减1。
package com.srzx.sms.listener;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
@WebListener()
public class OnlineListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
String name = se.getName();
//登录用户的session发生变化
if("account".equals(name)){
ServletContext application = se.getSession().getServletContext();
int online_num = application.getAttribute("online_num") == null ? 0 : (Integer) application.getAttribute("online_num");
System.out.println("online_num = " + online_num);
online_num++;
application.setAttribute("online_num",online_num);
}
String value = (String) se.getValue();
System.out.println("OnlineListener.attributeAdded");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
String name = se.getName();
//退出用户的session发生变化
if("account".equals(name)){
ServletContext application = se.getSession().getServletContext();
int online_num = application.getAttribute("online_num") == null ? 0 : (Integer) application.getAttribute("online_num");
System.out.println("online_num = " + online_num);
online_num--;
application.setAttribute("online_num",online_num);
}
}
}
<body>
<div class="container-fluid">
<div class="row">
<div class="jumbotron">
<h1>欢迎使用学生管理系统(SMS)</h1>
<p>该系统当前在线人数:${applicationScope.online_num},历史访问人数:1000.</p>
</div>
</div>
</div>
</body>
</html>