监听器
什么是监听器:
-
它是一个接口,内容由我们来实现;
-
它需要注册,例如注册在按钮上!
-
监听器中的方法,会在特殊事件发生时被调用!
JavaWeb中的监听器
ServletContext
- 生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
-
void contextInitialized(ServletContextEvent sce):创建Servletcontext时
-
void contextDestroyed(ServletContextEvent sce):销毁Servletcontext时
- 属性监听:ServletContextAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
-
void attributeAdded(ServletContextAttributeEvent event):添加属性时;
-
void attributeReplaced(ServletContextAttributeEvent event):替换属性时;
-
void attributeRemoved(ServletContextAttributeEvent event):移除属性时;
HttpSession
- 生命周期监听:HttpSessionListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
-
void sessionCreated(HttpSessionEvent se):创建session时
-
void sessionDestroyed(HttpSessionEvent se):销毁session时
- 属性监听:HttpSessioniAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
-
void attributeAdded(HttpSessionBindingEvent event):添加属性时;
-
void attributeReplaced(HttpSessionBindingEvent event):替换属性时
-
void attributeRemoved(HttpSessionBindingEvent event):移除属性时
ServletRequest
- 生命周期监听:ServletRequestListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
-
void requestInitialized(ServletRequestEvent sre):创建request时
-
void requestDestroyed(ServletRequestEvent sre):销毁request时
- 属性监听:ServletRequestAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
-
void attributeAdded(ServletRequestAttributeEvent srae):添加属性时
-
void attributeReplaced(ServletRequestAttributeEvent srae):替换属性时
-
void attributeRemoved(ServletRequestAttributeEvent srae):移除属性时
javaWeb中完成编写监听器:
编写一个生命周期监听器(以ServletContext为例)
-
写一个监听器类:要求必须去实现ServletContextListener监听器接口;
package cn.andios.test; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("创建ServletContext"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("销毁ServletContext"); } }
-
注册,是在web.xml中配置来完成注册!
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--注册监听器--> <listener> <listener-class>cn.andios.test.MyServletContextListener</listener-class> </listener> </web-app>
-
测试
启动服务器时控制台输出了“创建ServletContext”。
关闭服务器时控制台输出了“销毁ServletContext”
编写一个属性监听器(以ServletContext为例)
-
要求必须去实现ServletContextAttributeListener监听器接口;
package cn.andios.test; import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyServletContextAttributeListener implements ServletContextAttributeListener { //当添加属性时 @Override public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("向application中添加了"+servletContextAttributeEvent.getName()+"="+servletContextAttributeEvent.getValue()); } //当移除属性时 @Override public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("从application中移除了"+servletContextAttributeEvent.getName()+"="+servletContextAttributeEvent.getValue()); } //当替换属性时,这里得到的值是旧值 @Override public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("从application中替换了"+servletContextAttributeEvent.getName()+"="+servletContextAttributeEvent.getValue()); } }
-
注册,是在web.xml中配置来完成注册!
<!--注册ServletContext的属性监听器--> <listener> <listener-class>cn.andios.test.MyServletContextAttributeListener</listener-class> </listener>
-
测试
- 当在jsp页面执行了application.setAttribute(“aaa”,“aaa”);时,控制台输出“向application中添加了aaa=aaa”
- 当在jsp页面执行了application.setAttribute(“aaa”,“bbb”);时,控制台输出“从application中替换了aaa=aaa”
- 当在jsp页面执行了application.removeAttribute(“aaa”);时,控制台输出“从application中移除了aaa=aaa”
HttpSession的监听器
还有两个与HttpSession相关的特殊的监听器,这两个监听器的特点如下:
-
不用在web.xml文件中部署;
-
这两个监听器不是给session添加,而是给Bean添加。即让Bean类实现监听器接口,然后再把Bean对象添加到session域中。
HttpSessionBindingListener
- 当某个类实现了该接口后,可以感知本类对象添加到session中,以及感知从session中移除。例如让Person类实现HttpSessionBindingListener接口,那么当把Person对象添加到session中,或者把Person对象从session中移除时会调用下面两个方法:
-
public void valueBound(HttpSessionBindingEvent event):当把监听器对象添加到session中会调用监听器对象的本方法;
-
public void valueUnbound(HttpSessionBindingEvent event):当把监听器对象从session中移除时会调用监听器对象的本方法;
-
测试HttpSessionBindingListener
-
编写java类
package cn.andios.test; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; public class User implements HttpSessionBindingListener { @Override public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("我添加到session中了"); } @Override public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("我从session中移除了"); } }
-
在jsp中执行application.setAttribute(“aaa”,new User());,控制台输出了“我添加到session中了”
-
在jsp中执行session.removeAttribute(“aaa”);控制台输出了“我从session中移除了”
-
session序列化
-
当服务器启动时,向session中存入数据,重启服务器后,session中的数据居然还能取出来。这是因为,当服务器关闭时,把session对象序列化到了磁盘上。当服务器再次启动时,又把session反序列化了,所以还可以得到session中的信息。
-
若不想让服务器关闭时,序列化session,则在服务器的context.xml配置文件中加上
<Manager pathname="">
即可
session钝化
若服务器中有太多的访问用户,则占用的内存会很大。为了使内存占用不会过大,则服务器会把长时间无响应的session序列化到磁盘中(session的钝化),当用户再次活动时,再把session反序列化(session的活化)。这样就使得用户不会感受到自己掉线了。
-
要开启session的钝化与活化功能,则要在context.xml文件中添加
<Context> <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> <Store className="org.apache.catalina.session.FileStore" directory="mysession"/> </Manager> </Context>
HttpSessionActivationListener监听器
与HttpSessionBindingListener监听器相似,都是感知型的监听器,例如让Person类实现了HttpSessionActivationListener监听器接口,并把Person对象添加到了session中后,当Tomcat钝化session时,同时也会钝化session中的Person对象,这时Person对象就会感知到自己被钝化了,其实就是调用Person对象的sessionWillPassivate()方法。当用户再次使用session时,Tomcat会活化session,这时Person会感知到自己被活化,其实就是调用Person对象的sessionDidActivate()方法。
验证
-
编写一个User类,实现HttpSessionActivationListener监听器口和Serializable序列化接口
package cn.andios.test; import javax.servlet.http.HttpSessionActivationListener; import javax.servlet.http.HttpSessionEvent; import java.io.Serializable; public class User implements HttpSessionActivationListener, Serializable { private String name; private String password; public User(String name, String password) { this.name = name; this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } @Override public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) { System.out.println(httpSessionEvent.getSession().getAttribute("user")+"一起和session序列化到磁盘了"); } @Override public void sessionDidActivate(HttpSessionEvent httpSessionEvent) { System.out.println(httpSessionEvent.getSession().getAttribute("user")+"一起和session活化了"); } }
-
然后在jsp中执行
session.setAttribute("user",new User("张三","123456"));
,-
等待一分钟,控制台输出“User{name=‘张三’, password=‘123456’}一起和session序列化到磁盘了”
-
然后在继续操作页面,控制台输出“User{name=‘张三’, password=‘123456’}一起和session活化了”
-
最后在jsp中执行
User user=session.getAttribute("user"); System.out.println(user)
控制台会输出User{name=‘张三’, password=‘123456’}对象
-
-
注意:要使对象一起被序列化到磁盘,则必须实现Serializable接口