主页 > 电脑硬件  > 

板块一Servlet编程:第十节监听器全解来自【汤米尼克的JAVAEE全套教程专栏】

板块一Servlet编程:第十节监听器全解来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程:第十节 监听器全解 一、什么是监听器实现一个监听器的简单流程 二、各对象的监听器使用方法(1)Request域的监听器(2)Session域的监听器(3)Application域的监听器 三、实例:监听器实现在线人数统计

在上一节中,我们学习的过滤器在JavaEE中主要对请求响应的过程做过滤,那么这节学习的监听器则主要在作用域生命周期的过程中做监听,二者都为我们实现了一两拨千斤的效果

一、什么是监听器 类似于前端中事件绑定,Java中的监听器用于监听web应用中某些对象(如ServletContext\HttpSeesion\ServletRequest等)、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等监听器按照不同监听对象可以分成三类,一共提供了八个监听器接口

第一类:Request对象的监听器

ServletRequestListener (处理request对象创建和销毁) ServleRequestAttributeListener (处理域对象中的数据添加 替换 删除)

第二类:Session对象的监听器

HttpSessionListener (处理session对象创建和销毁) HttpSessionAttributeListener (处理session域对象中的数据添加 修改 删除) HttpSessionBindingListener (处理session对象监听器绑定和解绑定接口) HttpSessionActivationListener (处理session对象钝化和活化状态接口)

第三类:Application对象的监听器

ServletContextListener (处理application对象创建和销毁) ServletContextAttributeListener (处理application域对象中的数据添加 修改 删除) 实现一个监听器的简单流程

实例:监听一个Seesion的生命周期 同样在 .caijiyuan下新建监听层的包Listener

包中新建监听器接口listenerSession,继承自HttpSessionListener 类,然后重写HttpSessionListener 监听Session生命周期的两个方法

@Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { }

在这两个方法中写入相应周期时要打印的内容方便观察 然后同样,别忘了在类前写入监听器的注释@WebListener,我们点开监听器的注释代码,会发现没有形参 因此监听器的注释只用写成@WebListener即可,不必配置文件站点名。另外,监听器与过滤器一样可以在web.xml中配置,但不如注释简洁 此时,监听器完整代码为

package .caijiyuan.Listener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; @WebListener public class listenerSession implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { System.out.println("Session被创建了"); } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("Seesion被销毁了"); } }

在start.java文件中写一个Session的创建销毁过程

package .caijiyuan.Servlt; 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("/start") public class start extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("访问到Start"); HttpSession session =req.getSession(); //创建Session session.invalidate(); //销毁Session } }

此时的项目结构为

启动服务器,在浏览器中访问start.java 即会在控制台打印 这就是监听器最简单的实现流程

二、各对象的监听器使用方法 (1)Request域的监听器

类似的,Request对象的监听器可以这样定义

import javax.servlet.*; @WebListener public class MyRequestListener implements ServletRequestListener, ServletRequestAttributeListener { @Override public void requestDestroyed(ServletRequestEvent sre) { // 监听HttpServletRequest对象的销毁 项目中任何一个Request对象的销毁都会触发该方法的执行 ServletRequest servletRequest = sre.getServletRequest(); System.out.println("request"+servletRequest.hashCode()+"对象销毁了"); } @Override public void requestInitialized(ServletRequestEvent sre) { // 监听HttpServletRequest对象的创建并初始化 项目中任何一个Request对象的创建并初始化都会触发该方法的执行 ServletRequest servletRequest = sre.getServletRequest(); System.out.println("request"+servletRequest.hashCode()+"对象初始化"); } @Override public void attributeAdded(ServletRequestAttributeEvent srae) { // 任何一个Request对象中调用 setAttribute方法增加了数据都会触发该方法 ServletRequest servletRequest = srae.getServletRequest(); String name = srae.getName(); Object value = srae.getValue(); System.out.println("request"+servletRequest.hashCode()+"对象增加了数据:"+name+"="+value); } @Override public void attributeRemoved(ServletRequestAttributeEvent srae) { // 任何一个Request对象中调用 removeAttribute方法移除了数据都会触发该方法 ServletRequest servletRequest = srae.getServletRequest(); String name = srae.getName(); Object value = srae.getValue(); System.out.println("request"+servletRequest.hashCode()+"对象删除了数据:"+name+"="+value); } @Override public void attributeReplaced(ServletRequestAttributeEvent srae) { // 任何一个Request对象中调用 setAttribute方法修改了数据都会触发该方法 ServletRequest servletRequest = srae.getServletRequest(); String name = srae.getName(); Object value = srae.getValue(); Object newValue=servletRequest.getAttribute(name); System.out.println("request"+servletRequest.hashCode()+"对象增修改了数据:"+name+"="+value+"设置为:"+newValue); } }

对应的测试start.java

@WebServlet("/start") public class start extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setAttribute("name", "Toomynike"); req.setAttribute("name", "NikeTommy"); req.removeAttribute("name"); } } (2)Session域的监听器

对于Session域的四个监听器接口:HttpSessionListener、HttpSessionAttributeListener、HttpSessionBindingListener、HttpSessionActivationListener中的前两个,可以这样使用

import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; @WebListener public class MySessionListener implements HttpSessionListener , HttpSessionAttributeListener { @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("任何一个Session对象创建"); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("任何一个Session对象的销毁"); } @Override public void attributeAdded(HttpSessionBindingEvent se) { System.out.println("任何一个Session对象中添加了数据"); } @Override public void attributeRemoved(HttpSessionBindingEvent se) { System.out.println("任何一个Session对象中移除了数据"); } @Override public void attributeReplaced(HttpSessionBindingEvent se) { System.out.println("任何一个Session对象中修改了数据"); } }

对于Sessiony域监听器的HttpSessionBindingListener接口可以这样使用

import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionActivationListener; import javax.servlet.http.HttpSessionEvent; @WebListener public class MySessionActivationListener implements HttpSessionActivationListener { @Override public void sessionWillPassivate(HttpSessionEvent se) { System.out.println("session即将钝化"); } @Override public void sessionDidActivate(HttpSessionEvent se) { System.out.println("session活化完毕"); } } (3)Application域的监听器

对于Application域的ServletContextListener , ServletContextAttributeListener监听器接口,可以这样使用

import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyApplicationListener implements ServletContextListener , ServletContextAttributeListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("ServletContext创建并初始化了"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("ServletContext销毁了"); } @Override public void attributeAdded(ServletContextAttributeEvent scae) { System.out.println("ServletContext增加了数据"); } @Override public void attributeRemoved(ServletContextAttributeEvent scae) { System.out.println("ServletContext删除了数据"); } @Override public void attributeReplaced(ServletContextAttributeEvent scae) { System.out.println("ServletContext修改了数据"); } } 三、实例:监听器实现在线人数统计

这个功能实现的抽象逻辑为:

当有新的Session对象创建时,在线人数+1当有Session对象被销毁时,在线人数-1

在Listener层下新建OnlineListener监听器用于实现核心逻辑,继承自HttpSessionListener之后,重写两个监听方法实现抽象逻辑

package .caijiyuan.Listener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; @WebListener public class OnlineListener implements HttpSessionListener { private Integer onlineNumber = 0; //保存在线人数 @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { onlineNumber++; httpSessionEvent.getSession().setAttribute("OnlineListener",onlineNumber); //将在线人数值存入Session } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { onlineNumber--; httpSessionEvent.getSession().setAttribute("OnlineListener",onlineNumber); } }

其中

httpSessionEvent.getSession().setAttribute("OnlineListener",onlineNumber); //将在线人数值存入Session

就是调用了httpSessionEvent实例,它可以把监听器中得到的参数存入Session方便我们在别的Servlet中调取

在start.java中访问创建Session并在浏览器打印在线人数

package .caijiyuan.Servlt; 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("/start") public class start extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("访问到Start"); HttpSession session =req.getSession(); // 用户来了创建Session // 得到当前作用域中的在线人数 Integer onlineNumber = (Integer) session.getAttribute("OnlineListener"); // 设置相应类型及编码 resp.setContentType("text/html;charset=UTF-8"); // 打印在线人数 resp.getWriter().write("<h1>当前在线人数:"+onlineNumber+"</h1>"); } }

启动服务器先后在本机电脑上的Google浏览器、Edge浏览器中访问start文件,即可得到 看似成功了,但还有一个小bug:当我们在线人数为2时,刷新Google浏览器会发现在线人数只会显示1,这是因为存储在Session中只能在当前浏览器中访问,数据不共享。此时就需要扩大域对象的范围了,把数据存在服务器数据域上:ServletContext对象。 还记得我们在ServletContext小节学习的获取 ServletContext 对象的几种方法吗? 其中的通过Session获取ServletContext 对象看似绕了一步,没必要,实则就在这里起到了作用,因为监听器给予的对象里面只有Session,因此只能通过Session获取ServletContext 对象 现在思路就很明确了,我们只需要将OnlineListener类中的两句

httpSessionEvent.getSession().setAttribute("OnlineListener",onlineNumber);

改成

httpSessionEvent.getSession().getServletContext().setAttribute("OnlineListener",onlineNumber);

在start.java中,将接受参数作用域也改成ServletContext对象

package .caijiyuan.Servlt; import javax.servlet.ServletContext; 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("/start") public class start extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("访问到Start"); HttpSession session =req.getSession(); // 用户来了创建Session // 得到当前作用域中的在线人数 ServletContext servletContext = getServletContext(); Integer onlineNumber = (Integer) servletContext.getAttribute("OnlineListener"); // 设置相应类型及编码 resp.setContentType("text/html;charset=UTF-8"); // 打印在线人数 resp.getWriter().write("<h1>当前在线人数:"+onlineNumber+"</h1>"); } }

与刚刚相同,先后在两个浏览器访问start文件,再刷新两个浏览器就能同步在线人数了

以上就是本小节,也是本专栏Servlet板块的全部内容了,欢迎读者在评论区提出意见反馈。博主也很乐于私信交流。下一个板块我们将着重详解Java EE的另一个基石:JSP和JSTL

标签:

板块一Servlet编程:第十节监听器全解来自【汤米尼克的JAVAEE全套教程专栏】由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“板块一Servlet编程:第十节监听器全解来自【汤米尼克的JAVAEE全套教程专栏】