一,监听器介绍
监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。
监听器的相关概念:
事件源 | 被监听的对象 |
监听器 | 监听事件源对象,事件源对象的状态的变化都会触发监听器 |
注册监听器 | 将监听器与事件源进行绑定。 |
响应行为 | 监听器监听到事件源的状态变化时 所涉及的功能代码。 |
二,监听器的分类
分类1:按照被监听的对象划分
ServletRequest域
HttpSession域
ServletContext域
分类2:监听的内容分
监听域对象的创建与销毁的
监听域对象的属性变化的
三,监听三大域对象的创建与销毁的监听器
监听器的编写步骤:
1、编写一个监听器类去实现监听器接口
2、覆盖监听器的方法
3、需要在web.xml中进行配置
1,监听ServletContext域的创建与销毁的监听器ServletContextListener
当ServletContext对象被创建时,触发contextInitialized (ServletContextEvent arg0)方法。
当ServletContext对象被销毁时,触发contextDestroyed(ServletContextEvent arg0)方法。
ServletContext域对象创建和销毁时机:
创建:服务器启动针对每一个Web应用创建ServletContext。
销毁:服务器关闭前先关闭代表每一个web应用的ServletContext。
例如:
import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener; public class MyServletContextListener implements ServletContextListener{ @Override public void contextDestroyed(ServletContextEvent arg0) { System.out.println("ServletContext对象销毁了!"); } @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("ServletContext对象创建了!"); }}
在web.xml文件中注册监听器:
Listener index.jsp com.zender.MyServletContextListener
web服务器启动:
web服务器关闭:
2,监听Httpsession域的创建于销毁的监听器HttpSessionListener
当创建一个Session时,触发sessionCreated (HttpSessionEvent arg0) 方法
当销毁一个Session时,触发sessionDestroyed (HttpSessionEvent arg0) 方法。
Httpsession域对象创建和销毁时机:
创建:第一次调用request.getSession时创建。
销毁:服务器关闭销毁 session过期 手动销毁。
例如:
import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener; public class MyHttpSessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent arg0) { System.out.println("session创建:" + arg0.getSession().getId()); } @Override public void sessionDestroyed(HttpSessionEvent arg0) { System.out.println("session销毁了!"); }}
在web.xml文件中注册监听器:
Listener index.jsp com.zender.MyHttpSessionListener
访问页面时:
3,监听ServletRequest域创建与销毁的监听器ServletRequestListener
当Request对象被创建时,触发requestInitialized(ServletRequestEvent arg0)方法。
当Request对象被销毁时,触发requestDestroyed(ServletRequestEvent arg0)方法。
ServletRequest域对象创建和销毁时机:
创建:用户每一次访问都会创建request对象
销毁:当前访问结束,request对象就会销毁
例如:
import javax.servlet.ServletRequestEvent;import javax.servlet.ServletRequestListener; public class MyServletRequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent arg0) { System.out.println("request对象销毁了"); } @Override public void requestInitialized(ServletRequestEvent arg0) { System.out.println("request对象创建了"); }}
在web.xml文件中注册监听器:
Listener index.jsp com.zender.MyServletRequestListener
访问页面时:
可以看出用户每一次访问都会创建request对象,当访问结束后,request对象就会销毁。
四.监听三大域对象的属性变化的监听器
1,监听ServletContext域的属性变化的监听器ServletContextAttributeListener
当ServletContext对象添加属性时,触发attributeAdded(ServletContextAttributeEvent arg0)方法。
当ServletContext对象修改属性时,触发attributeReplaced(ServletContextAttributeEvent arg0)方法。
当ServletContext对象删除属性时,触发attributeRemoved(ServletContextAttributeEvent arg0)方法。
例如:
import javax.servlet.ServletContextAttributeEvent;import javax.servlet.ServletContextAttributeListener; public class MyServletContextAttributeListener implements ServletContextAttributeListener { @Override public void attributeAdded(ServletContextAttributeEvent arg0) { System.out.println("属性被添加,name:" + arg0.getName() + "value:" + arg0.getValue()); } @Override public void attributeRemoved(ServletContextAttributeEvent arg0) { System.out.println("属性被删除,name:" + arg0.getName() + "value:" + arg0.getValue()); } @Override public void attributeReplaced(ServletContextAttributeEvent arg0) { //获得是修改前的数据 System.out.println("属性被修改,name:" + arg0.getName() + "value:" + arg0.getValue()); }}
Servlet:
import java.io.IOException; import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; public class TestMyServletContextAttributeListener extends HttpServlet{ private static final long serialVersionUID = -7057319189693064505L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); //存储一个数据 context.setAttribute("name", "Zender"); //修改一个数据 context.setAttribute("name", "Zender2"); //删除一个数据 context.removeAttribute("name"); }}
在web.xml文件中注册监听器和Servlet:
Listener index.jsp TestMyServletContextAttributeListener com.zender.servlet.TestMyServletContextAttributeListener TestMyServletContextAttributeListener /index.html com.zender.MyServletContextAttributeListener
访问http://localhost:8081/Listener/index.html,后台结果:
2, HttpSessionAttributeListener监听器(同上)
3,ServletRequestAriibuteListenr监听器(同上)
五,与session中的绑定的对象相关的监听器(对象感知监听器)
即将要被绑定到session中的对象有4种状态:
绑定状态 | 就一个对象被放到session域中 |
解绑状态 | 就是这个对象从session域中移除了 |
钝化状态 | 是将session内存中的对象持久化(序列化)到磁盘 |
活化状态 | 就是将磁盘上的对象再次恢复到session内存中 |
1,绑定与解绑的监听器HttpSessionBindingListener
当Person类在HttpSession对象绑定属性时,触发valueBound(HttpSessionBindingEvent arg0)方法。
当Person类在HttpSession对象解绑属性时,触发valueUnbound(HttpSessionBindingEvent arg0)方法。
例如:
首先创建一个Person类实现HttpSessionBindingListener接口:
public class Person implements HttpSessionBindingListener { private int id; private String name; public int getId() { return id; } public Person(int id, String name) { this.id = id; this.name = name; } public Person() { } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void valueBound(HttpSessionBindingEvent arg0) { System.out.println("person对象被绑定了!"); } @Override public void valueUnbound(HttpSessionBindingEvent arg0) { System.out.println("person对象被解绑了!"); } }
Servlet:
import java.io.IOException; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession; import com.zender.Person; public class TestPersonBindingListener extends HttpServlet { private static final long serialVersionUID = -4836536065640905707L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); //将Person绑定到Session域中 session.setAttribute("persion", new Person(1,"Zender")); //将Person从Session域中解绑 session.removeAttribute("persion"); }}
在web.xml文件中注册Servlet:
Listener index.jsp TestPersonBindingListener com.zender.servlet.TestPersonBindingListener TestPersonBindingListener /index.html
访问http://localhost:8081/Listener/index.html,后台结果:
2,钝化与活化的监听器HttpSessionActivationListener
当Person类被钝化时,触发sessionWillPassivate(HttpSessionEvent arg0)方法。
当Person类被活化时,触发sessionDidActivate(HttpSessionEvent arg0)方法。
例如:
首先创建一个Person类实现HttpSessionActivationListener接口,并且这个类必须实现Serializable接口(序列化):
public class Person implements HttpSessionActivationListener,Serializable{ private int id; private String name; public int getId() { return id; } public Person(int id, String name) { this.id = id; this.name = name; } public Person() { } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void sessionDidActivate(HttpSessionEvent arg0) { System.out.println("Person被活化了"); } @Override public void sessionWillPassivate(HttpSessionEvent arg0) { System.out.println("Person被钝化了"); }}
Servlet:
import java.io.IOException; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession; import com.zender.Person; public class TestPersonActivationListener extends HttpServlet { private static final long serialVersionUID = -4836536065640905707L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); //将Person绑定到Session域中 session.setAttribute("persion", new Person(1,"Zender")); System.out.println("Person被放到Session域中了!"); }}
在web.xml文件中注册Servlet:
Listener index.jsp TestPersonActivationListener com.zender.servlet.TestPersonActivationListener TestPersonActivationListener /index.html
访问http://localhost:8081/Listener/index.html,后台结果:
关闭服务器:
控制台打印:
钝化的文件:
活化对象:
Servlet2:
import java.io.IOException; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession; import com.zender.Person; public class TestPersonActivationListener2 extends HttpServlet { private static final long serialVersionUID = -4836536065640905707L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); //获取Session域中的Person Person p = (Person) session.getAttribute("persion"); System.out.println("name:" + p.getName()); }}
在web.xml文件中注册Servlet2:
TestPersonActivationListener2 com.zender.servlet.TestPersonActivationListener2 TestPersonActivationListener2 /index2.html
启动服务器自动活化对象:
访问:http://localhost:8081/Listener/index2.html,控制台打印:
怎么控制对象的钝化时间呢?可以通过配置文件,指定对象钝化时间,对象多长时间不用会被钝化。
在META-INF下创建一个context.xml
内容如下:
启动服务器访问Servlet把对象放到Session中:
控制台:过1分钟后对象会被自动钝化:
钝化的文件:
访问Servlet2时,对象会自动被活化: