①监听器是Servlet规范中的一员。就像Filter一样。Filter也是Servlet规范中的一员。
②在Servlet中,所有的监听器接口都是以“Listener”结尾。
③监听器实际上是Servlet规范留给我们javaweb程序员的特殊时机。
④特殊的时刻如果想执行这段代码,你需要想到使用对应的监听器。
javax.servlet包下:
①ServletContextListener
②ServletContextAttributeListener
③ServletRequestListener
④ServletRequestAttributeListener
jakarta.servlet.http包下:
①HttpSessionListener
②HttpSessionAttributeListener
③HttpSessionBindingListener
④HttpSessionIdListener
⑤HttpSessionActivationListener
这里主要先讲解熟悉的关于三个域对象的监听器:
ServletContext、ServletRequest、HttpSession
(1)以ServletContextListener为例
①第一步:编写一个类实现ServletContextListener接口。并且实现里面的方法。
监听器中的方法不需要程序员手动调用。是发生某个特殊事件之后被服务器调用。
// ServletContext对象被创建的时候调用。 void contextInitialized(ServletContextEvent event) // ServletContext对象被销毁的时候调用 void contextDestroyed(ServletContextEvent event)
②第二步:在web.xml文件中对ServletContextListener进行配置,如下:
当然,第二步也可以不使用配置文件,也可以用注解,例如:@WebListener 即可。
<listener> <listener-class>com.bjpowernode.javaweb.servlet.MyServletContextListener</listener-class> </listener>
注意:所有监听器中的方法都是不需要javaweb程序员调用的,由服务器来负责调用。
什么时候被调用呢?当某个特殊的事件发生(特殊的事件发生其实就是某个时机到了)之后,被web服务器自动调用。
③服务器启动时,ServletContext对象创建,contextInitialized方法执行
服务器关闭时,ServletContext对象销毁,contextDestroyed方法执行
package com.bjpowernode.javaweb.servlet; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * @Package:com.bjpowernode.javaweb.servlet * @Project:JavaWeb * @name:MyServletContextListener */ // ServletContextListener监听器主要监听的是:ServletContext对象的状态。 public class MyServletContextListener implements ServletContextListener { // 服务器启动时间点 /** * 监听器中的方法不需要程序员手动调用。是发生某个特殊事件之后被服务器调用。 * @param sce */ @Override public void contextInitialized(ServletContextEvent sce) { // 服务器关闭时间点 // 现在这个特殊的时刻写代码,你写就是了。它会被服务器自动调用。 // 这个方法是在ServletContext对象被创建的时候调用。 System.out.println("ServletContext对象创建了。"); } @Override public void contextDestroyed(ServletContextEvent sce) { // 现在这个特殊的时刻写代码,你写就是了。它会被服务器自动调用。 // 这个方法是在ServletContext对象被销毁的时候调用。 System.out.println("ServletContext对象被销毁了。"); } }
(2)以ServletRequestListener为例
④ServletRequest对象是一次请求创建一个request对象,所以服务器启动后:
只要发送一次请求就会调用requestInitialized方法,请求结束立刻会调用requestDestroyed
注:我们直接访问http://localhost:8080/servlet15/会报404错误,因为默认会访问index.html,但是我们并没有写;就算如此也会发送出请求,执行这个监听器。
package com.bjpowernode.javaweb.servlet; import javax.servlet.ServletContextEvent; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; /** * @Package:com.bjpowernode.javaweb.servlet * @Project:JavaWeb * @name:MyServletRequestListener */ @WebListener public class MyServletRequestListener implements ServletRequestListener { // request对象销毁时间点 @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("request对象销毁了"); } // request对象创建时间点 @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("request对象初始化了"); } }
(3)以HttpSessionListener为例
⑤我们都知道在访问jsp时,默认会创建session对象(九大内置对象);先编写一个my.jsp;在访问my.jsp时,会创建session对象,调用 sessionCreated方法;
当退出系统时,我们编写销毁session对象的方法,会调用sessionDestroyed方法。
<%@ page contentType="text/html;charset=UTF-8" %> <html> <head> <title>Title</title> </head> <body> my jsp page <a href="${pageContext.request.contextPath}/exit" rel="external nofollow" >退出系统</a> </body> </html>
根据/exit请求,编写销毁session对象的类
package com.bjpowernode.javaweb; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; /** * @Package:com.bjpowernode.javaweb * @Project:JavaWeb * @name:ExitServlet */ @WebServlet("/exit") public class ExitServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取session对象 HttpSession session = request.getSession(false); if (session != null) { // 销毁session session.invalidate(); } } }
(4)AttributeListener的使用
①我们知道对于域对象都有setAttribute、getAttribute、removeAttribute方法,分别可以向域中存数据、取数据、清除数据;所以对于AttributeListener肯定是和这些处理域中数据有关。
②实际上对于ServletContextAttributeListener、ServletRequestAttributeListener 、HttpSessionAttributeListener这三个对象都有attributeAdded、attributeRemoved、attributeReplaced方法;表示:向域当中存储数据的时候调用、向域当中删除数据的时候调用、向域当中替换数据的时候调用。
③这里以HttpSessionAttributeListener对象为例:
编写HttpSessionAttributeListener监听器
package com.bjpowernode.javaweb.servlet; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionActivationListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; /** * @Package:com.bjpowernode.javaweb.servlet * @Project:JavaWeb * @name:MyHttpSessionAttributeListener */ @WebListener public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener { // 向session域当中存储数据的时候,以下方法被WEB服务器调用。 @Override public void attributeAdded(HttpSessionBindingEvent se) { System.out.println("session data add"); } // 将session域当中存储的数据删除的时候,以下方法被WEB服务器调用。 @Override public void attributeRemoved(HttpSessionBindingEvent se) { System.out.println("session data remove"); } // session域当中的某个数据被替换的时候,以下方法被WEB服务器调用。 @Override public void attributeReplaced(HttpSessionBindingEvent se) { System.out.println("session data replace"); } }
编写Servlet类用来处理域中的数据
当发送http://localhost:8080/servlet15/session/attribute/test就能触发上面的监听器;
注意:调用getAttribute方法不会触发,只有setAttribute方法和removeAttribute方法才会触发
package com.bjpowernode.javaweb; 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 java.io.IOException; /** * @Package:com.bjpowernode.javaweb * @Project:JavaWeb * @name:HttpSessionAttributeServlet */ @WebServlet("/session/attribute/test") public class HttpSessionAttributeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取session对象 HttpSession session = request.getSession(); // 向session域中存储数据 session.setAttribute("user", "zhangsan"); // 替换,覆盖上面的数据 session.setAttribute("user", "lisi"); // 删除 session.removeAttribute("user"); } }
(1)前面我们已经讲解了关于域对象的监听器,九个监听器中就已经学习了6个;接下来就先分析一下HttpSessionBindingListener;顾名思义就是关于数据绑定的!
(2)下面就通过一个例子来学习一下HttpSessionBindingListener监听器:
创建一个user1类实现监听器(不需要@WebListener注解),并重写方法
创建一个user2类不实现监听器
对比当数据放入放入域当中,两者会有什么区别:
①普通的user1类实现监听器,并重写监听器中两个方法
package com.bjpowernode.javaweb.bean; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; /** * 普通的java类。但是它实现了:HttpSessionBindingListener */ public class User1 implements HttpSessionBindingListener { @Override public void valueBound(HttpSessionBindingEvent event) { System.out.println("绑定数据"); } @Override public void valueUnbound(HttpSessionBindingEvent event) { System.out.println("解绑数据"); } private String usercode; private String username; private String password; public User1(String usercode, String username, String password) { this.usercode = usercode; this.username = username; this.password = password; } public User1() { } public String getUsercode() { return usercode; } public void setUsercode(String usercode) { this.usercode = usercode; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
②普通的user2类不实现监听器
package com.bjpowernode.javaweb.bean; /** * 普通的java类。 */ public class User2 { private String usercode; private String username; private String password; public User2() { } public User2(String usercode, String username, String password) { this.usercode = usercode; this.username = username; this.password = password; } public String getUsercode() { return usercode; } public void setUsercode(String usercode) { this.usercode = usercode; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
③编写一个servlet类,把这两种数据都存进去
发现实现监听器的user1类会触发绑定事件!
package com.bjpowernode.javaweb.servlet; import com.bjpowernode.javaweb.bean.User1; import com.bjpowernode.javaweb.bean.User2; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; @WebServlet("/session/bind") public class HttpSessionBindingListenerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取session对象 HttpSession session = request.getSession(); // 准备两个对象:User1 User2 User1 user1 = new User1("111", "zhangsan", "123"); User2 user2 = new User2("111", "zhangsan", "123"); // 将user1存储到session域 session.setAttribute("user1", user1); // 将user2存储到session域 session.setAttribute("user2", user2); } }
(3)区分:HttpSessionAttributeListener 和HttpSessionBindingListener