作用
监听域对象(请求request、会话session、应用servletContext)的创建和销毁
监听域对象的属性变更
监听HttpSession中JavaBean的状态改变(了解)
分类
第一类
监听域对象的创建和销毁
域对象类型 | 监听器 | 对应方法 | 描述 |
---|---|---|---|
ServletContext | ServletContextListener | contextInitialized | application初始化 |
contextDestroyed | application销毁 | ||
HttpSession | HttpSessionListener | sessionCreated | session创建 |
sessionDestroyed | session销毁 | ||
HttpServletRequest | ServletRequestListener | requestInitialized | request创建 |
requestDestroyed | request销毁 |
第二类
监听域对象的属性变更
域对象类型 | 监听器 | 对应方法 | 描述 |
---|---|---|---|
ServletContext | ServletContextAttributeListener | attributeAdded | 添加属性 |
attributeRemoved | 删除属性 | ||
attributeReplaced | 修改属性值 | ||
HttpSession | HttpSessionAttributeListener | attributeAdded | 添加属性 |
attributeRemoved | 删除属性 | ||
attributeReplaced | 修改属性值 | ||
HttpServletRequest | ServletRequestAttributeListener | attributeAdded | 添加属性 |
attributeRemoved | 删除属性 | ||
attributeReplaced | 修改属性值 |
第三类
监听HttpSession中JavaBean的状态改变(了解)
第三类监听器非常特殊,这类监听器不用配置
在JavaBean上,JavaBean可以自己感知在session中状态
域对象类型 | 监听器 | 对应方法 | 描述 |
---|---|---|---|
HttpSession | HttpSessionBindingListener | valueBound | 绑定 |
valueUnbound | 解除绑定 | ||
HttpSession | HttpSessionActivationListener | sessionWillPassivate | 序列化(钝化) |
sessionDidActivate | 反序列化(活化) |
session的钝化与活化
session 钝化本质就是服务器把内存中的session对象序列化到存储设备中,活化就是通过反序列化将session对象从存储设备上进行恢复 session 数据正常是存放在服务器内存当中的,当网站有大量用户访问时,服务器会创建大量的会话,这会占用大量的服务器内存资源,直接影响Web服务器的性能。此时服务器会将不常使用的session对象保存到文件系统或数据库中以节省内存开销,此即为session的钝化。当需要使用时再重新加载到内存,就称为session的活化 除此以外,Tomcat服务器在以下几种情况时也会执行session的钝化和活化操作 当服务器因为某些原因或因维护的需要进行关闭或短暂重启时,为了不丢失当前的会话信息以便在重启之后能够恢复会话,Tomcat服务器会将当前内存中的session对象钝化到服务器文件系统中,待系统恢复后再进行活化 另一种情况是当Web应用被服务器重新加载时,内存中的session对象也会被钝化到服务器的文件系统中,应用加载完毕后再进行活化 需要注意的是,session钝化操作时,session作用域中的变量只有实现了java.io.Serializable接口才能被钝化存储,否则将在钝化时被丢弃 如果需要在session钝化或者活化时执行特定的操作,可以将一个实现了javax.servlet.http.HttpSessionActivationListener接口的类(同时应实现java.io.Serializable接口)实例放入session作用域,通过该接口的sessionWillPassivate()方法和sessionDidActivate( )方法即可在session钝化和活化时执行所需的操作 HttpSessionActivationListener类型的监听器同样不需要在web.xml文件中进行声明、将其实例放入session作用域即可
案例
分析
统计在线人数
统计在线登录人数
需要使用三个监听器
-
监听servletContext对象的创建:该对象创建时,初始化两个key,用于保存在线人数和在线登录人数
-
监听session对象的创建和销毁:统计在线人数的增和减
-
监听session对象的属性变更:统计在线登录人数的增减
// 利用Java多实现的特性同时实现三个监听接口
//ServletContextListener:监听ServletContext对象的创建
//HttpSessionListener:监听HttpSession对象的创建和销毁
//HttpSessionAttributeListener:监听HttpSession对象的属性变更
@WebListener
public class CountListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {
/*************************ServletContextListener的方法***********************/
//ServletContext对象创建时执行的方法:初始化两个保存在线人数、在线登录人数数据
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//通过形参获取servletContext
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("onlineUserNum", 0);
servletContext.setAttribute("onlineLoginUserNum", 0);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
/*************************HttpSessionListener的方法***********************/
// 创建一个执行一次
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext sc = httpSessionEvent.getSession().getServletContext();
// 获取Session值并+1
Integer onlineUserNum = (Integer) sc.getAttribute("onlineUserNum");
sc.setAttribute("onlineUserNum", ++onlineUserNum);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
ServletContext sc = session.getServletContext();
Integer onlineUserNum = (Integer) sc.getAttribute("onlineUserNum");
sc.setAttribute("onlineUserNum", --onlineUserNum);
Object loginUser = session.getAttribute("loginUser");
if (null != loginUser) {
Integer onlineLoginUserNum = (Integer) sc.getAttribute("onlineLoginUserNum");
sc.setAttribute("onlineLoginUserNum", --onlineLoginUserNum);
}
}
/*************************HttpSessionAttributeListener的方法***********************/
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
//获取向session对象中保存的key的名称
String name = httpSessionBindingEvent.getName();
ServletContext sc = httpSessionBindingEvent.getSession().getServletContext();
//在线登录人数加1
if ("loginUser".equals(name)) {
Integer onlineLoginUserNum = (Integer) sc.getAttribute("onlineLoginUserNum");
sc.setAttribute("onlineLoginUserNum", ++onlineLoginUserNum);
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
//获取向session对象中保存的key的名称
String name = httpSessionBindingEvent.getName();
ServletContext sc = httpSessionBindingEvent.getSession().getServletContext();
//在线登录人数加1
if ("loginUser".equals(name)) {
Integer onlineLoginUserNum = (Integer) sc.getAttribute("onlineLoginUserNum");
sc.setAttribute("onlineLoginUserNum", --onlineLoginUserNum);
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {}
}