JavaWeb开发Listener学习

简介: JavaWeb开发Listener学习

博主信息:

📢@博主: 嘟嘟的程序员铲屎官
💬:一位爱喵咪,爱开源,爱总结,爱分享技术的Java领域新星博主,如果你想和博主做朋友,关注博主,并私聊博主(给我发一条消息我就会关注你喔),博主本人也十分喜欢解决问题,如果你有什么问题,也可以来私聊博主喔,希望能够和C站的朋友相互学习,相互进步。
💬:关于本篇博客,最近在学习JavaWeb部分的知识,对<<JavaWeb入门经典>>本书第7章第5节Listener监听器进行个人总结,如果有什么错误的,请各位大佬能够及时提出,以免小弟误人子弟!

@Toc

一.Listener监听器

1.什么是Listener监听器

在Servlet技术中定义很多的事件,为了对这些事件进行处理,针对这些事件编写相关的事件监听器,从而使用监听器处理事件,本篇博客主要讲解三大域对象(ServletContext、HttpSession、ServletRequest)的监听器,三大域对象的监听器分别对应的事件ServletContextEvent(上下文事件),HttpSessionEvent(会话事件),
HttpServletRequestEvent(请求事件)。

2.Listener简介

通过Listener接口对事件进行监听,下表列出常用8个Listener接口和6个Event类
在这里插入图片描述
在这里插入图片描述

servlet-api.jar中一共有13个和Listener相关的.java

在这篇博客<<JavaWeb开发Filter学习>>下第3.Filter的核心对象知识点中我们对servlet-api.jar进行了解压,并对javax.servlet包下的*.class文件进行了反编译,我们看看在servlet反编译文件下有哪一些Java文件跟Listener相关。

在javax.servlet包下和Listener相关的.Java文件(7个):
进入到servlet反编译文件中
在这里插入图片描述
在文件搜索框中输入*listener*

在这里插入图片描述
在原包(javax.servlet解压包)中进行我们可以发现annotation和http文件都存在以Listener相关的.class文件,分别对这二个包进行反编译
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在javax.servlet.annotation包下和Listener相关的.Java文件(1个):
在这里插入图片描述

在javax.servlet.http包下和Listener相关的.class文件(5个):
由于http包下的.class文件有的没有反编译成功,所以就在原包中进行搜索与Listener相关的.class
在这里插入图片描述

3.使用监听器

使用监听器有以下二个步骤:

  • 创建监听器(只要创建一个实现相关接口的Java类即可)
  • 注册监听器

注册监听器的二种方式:
使用@webListener标签进行注册

 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/16635a7e746144c0853bc4fcacd6b1c0.png)

在web.xml中使用部署描述符进行注册 在这里插入图片描述

4.Servlet Context监听器

Servlet Context监听器可以监听ServletContext对象的创建、删除和添加属性,以及删除和修改操作,该监听器需要用到如下两个接口,该接口都是javax.servlet包下的成员。

(1) ServletContextListener接口
  • 该接口位于javax.servlet下
  • 主要监听ServletContext的创建和删除。
  • 它提供了二个抽象方法:
    contextInitialized();contextDestroyed()

在这里插入图片描述
在这里插入图片描述

<<JavaWeb入门经典>>本书对这二个抽象方法的解释:
在这里插入图片描述

(2) ServletAttributeListener接口
  • 该接口位于javax.servlet下
  • 主要监听ServletContext属性的增加、删除及修改
  • 它提供了3个抽象方法:

attributeAdded();attributeRemoved();attributeReplaced()

在这里插入图片描述

在这里插入图片描述
<<JavaWeb入门经典>>本书对这三个抽象方法的解释:
在这里插入图片描述

5.Session 监听器

与HttpSession有关的监听器接口有4个:HttpSessionListener、HttpSessionActivation-Listener、HttpSessionAttributeListener和 HttpSessionBindingListener。这些接口都是javax.servlet.http包的成员,下面将进行详细的讲解。
(1) HttpSessionListener接口
  • 该接口位于javax.servlet.http包下
  • 该接口监听HTTP会话的创建及销毁,它提供了如下两个抽象方法。

sessionCreated();sessionDestroyed()

在这里插入图片描述
在这里插入图片描述

<<JavaWeb入门经典>>本书对这二个抽象方法的解释:
在这里插入图片描述
在这里插入图片描述

(2) HttpSessionAttributeListener接口
  • 该接口位于javax.servlet.http包下
  • 该接口实现监听 HTTP会话中属性的设置请求(属性添加,删除,替换),它提供了如下三个方法。

attributeAdded();attributeRemoved();attributeReplaced();
在这里插入图片描述
在这里插入图片描述

<<JavaWeb入门经典>>本书对这三个抽象方法的解释:
在这里插入图片描述

(3) HttpSessionActivationListener接口
  • 该接口位于javax.servlet.http包下
  • 该接口实现监听HTTP会话active和 passivate情况,它提供了如下2个方法。

sessionWillPassivate();sessionDidActivate()

在这里插入图片描述
在这里插入图片描述
<<JavaWeb入门经典>>本书对这二个抽象方法的解释:
在这里插入图片描述

(4) HttpSessionBindingListener接口
  • 该接口位于javax.servlet.http包下
  • 该接口实现监听HTTP会话中对象的绑定信息,它是唯一不需要在web.xml中设置Listener的,并提供了以下两个方法。

valueBound();valueUnbound();

在这里插入图片描述
在这里插入图片描述
<<JavaWeb入门经典>>本书对这二个抽象方法的解释:
在这里插入图片描述

6.ServletRequest 监听器

在ServletRequest级别上有3个监听器接口:ServletRequestListener、ServletRequestAttributeListener和AsyncListener,这些接口都是javax.servlet包的成员。下面主要讲解了前二种接口。
(1) ServletRequestListener接口
  • 该接口位于javax.servlet包下
  • ServletRequestListener对 ServletRequest的创建和销毁做出响应。
  • 该接口提供如下二个方法

requestDestroyed();requestInitialized();

在这里插入图片描述
在这里插入图片描述
<<JavaWeb入门经典>>本书对这二个抽象方法的解释:
在这里插入图片描述

(2) ServletRequestAttributeListener接口
  • 该接口位于javax.servlet包下
  • 当在ServletRequest中添加删除或者替换某个属性时会调用以下三个方法

attributeAdded();attributeRemoved();attributeReplaced();
在这里插入图片描述

在这里插入图片描述
<<JavaWeb入门经典>>本书对这三个抽象方法的解释:
在这里插入图片描述

7.实例练习(使用监听器统计在线用户及人数)

分析:
在这里插入图片描述

项目结构:
在这里插入图片描述
index.html
在这里插入图片描述
web.xml
(在web.xml中配置session-timeout标签 标志session过期时间为1分钟 0为不过期)
在这里插入图片描述
HttpSessionListener.java

@WebListener
public class HttpSessionListener implements javax.servlet.http.HttpSessionListener{

    private int userCounts=0;
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        // TODO Auto-generated method stub
        httpSessionEvent.getSession().setAttribute("userCounts", ++userCounts);
        
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        // TODO Auto-generated method stub
        // 将人数数据加到HttpSession中
        httpSessionEvent.getSession().setAttribute("userCounts", --userCounts);
        
        // 获取用户列表
        @SuppressWarnings("unchecked")
        ArrayList<User> list=(ArrayList<User>)httpSessionEvent.
                getSession().getServletContext().getAttribute("userList ");
        
        
        if (list!=null) {
            // 根据SessionId属性将当前用户从userList集合中移除
            for (User user : list) {
                if (user.getSessionId().equals(httpSessionEvent.getSession().getId())) {
                    list.remove(user);
                }
            }    
        }
    }
    


}

ServletRequestListener.java


@WebListener
public class ServletRequestListener implements javax.servlet.ServletRequestListener{

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        // TODO Auto-generated method stub
        // 获取ServletContext中的userList集合
        @SuppressWarnings("unchecked")
        ArrayList<User> list=(ArrayList<User>)servletRequestEvent.getServletContext().getAttribute("userList");
        // ServletContext是否创建,未创建返回的集合为null,需要进行初始化
        if (list==null) {
            list=new ArrayList<>();
        }
        // 创建HttpServletRequest对象
        HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequestEvent.getServletRequest();
        
        // 当前用户是否在该集合中,没有则将用户信息加入到集合中去,并保存到ServletContext中
        if (noAtUserList(list,httpServletRequest)) {
            // 将当前用户添加到userList集合中
            User user=new User();
            user.setSessionId(httpServletRequest.getSession().getId());
            user.setIp(httpServletRequest.getRemoteAddr()); 
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:MM:ss"); 
            user.setFirstTime(sdf.format(new Date())); 
            list.add(user); 
        }
        
        // 将数据保存到ServletContext中
        servletRequestEvent.getServletContext().setAttribute("userList", list);
    }
    
    @SuppressWarnings("unused")
    private boolean noAtUserList(ArrayList<User>list,HttpServletRequest httpServletRequest) {
        for (User user : list) {
            if (user.getSessionId().equals(httpServletRequest.getSession().getId())) {
                return false;
            }
        }
        return true;
    }

}

User.java

public class User { 
      // 当前用户的session id 
      private String sessionId; 
      // 当前用户的ip地址 
      private String ip; 
      // 当前用户第一次访问的时间 
      private String firstTime; 

      
      public String getIp() { 
        return ip; 
      } 
      public void setIp(String ip) { 
        this.ip = ip; 
      } 
      public String getFirstTime() { 
        return firstTime; 
      } 
      public void setFirstTime(String firstTime) { 
        this.firstTime = firstTime; 
      } 
      public String getSessionId() { 
        return sessionId; 
      } 
      public void setSessionId(String sessionId) { 
        this.sessionId = sessionId; 
      }
      
}

usersInfoservlet.java


@SuppressWarnings("serial")
@WebServlet(urlPatterns={"/usersInfo"})
public class usersInfoservlet extends HttpServlet{
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // TODO Auto-generated method stub
            // 设置网页编码,防止出现乱码
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            resp.setHeader("content-type", "text/html;charset=UTF-8");
            
            // 获取userList
            @SuppressWarnings({ "unused", "unchecked" })
            ArrayList<User>userList=(ArrayList<User>)req.getServletContext().getAttribute("userList");
            // 获取当前用户数
            int userCounts=((req.getSession().getAttribute("userCounts") == null) ? 0:(int) req.getSession().getAttribute("userCounts"));

            
            // 显示信息
            PrintWriter writer=resp.getWriter();
            writer.print("<html><head></head>");
            writer.print("<body>当前人数:"+userCounts+"</br>");
            if (userList!=null) {
                for (int i = 0; i < userList.size(); i++) {
                    writer.print("第"+(i+1)+"个用户,信息:</br>");
                    writer.print("sessionId:"+userList.get(i).getSessionId()+"</br>");
                    writer.print("ip:"+userList.get(i).getIp()+"</br>");
                    writer.print("firstTime:"+userList.get(i).getFirstTime()+"</br>");
                }
            }
            writer.print("</body></html>");
        }
        
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
            doGet(req, resp);
        }
}

运行效果:
在这里插入图片描述
在这里插入图片描述
打开另外一个游览器,访问:http://localhost:8085/app05/usersInfo
在这里插入图片描述
再打开一个游览器,再次访问
在这里插入图片描述

相关文章
|
3天前
|
人工智能 自然语言处理 Java
Spring AI,Spring团队开发的新组件,Java工程师快来一起体验吧
文章介绍了Spring AI,这是Spring团队开发的新组件,旨在为Java开发者提供易于集成的人工智能API,包括机器学习、自然语言处理和图像识别等功能,并通过实际代码示例展示了如何快速集成和使用这些AI技术。
Spring AI,Spring团队开发的新组件,Java工程师快来一起体验吧
|
4天前
|
前端开发 Java 编译器
【前端学java】如何从前端视角快速学习Maven
【8月更文挑战第12天】如何从前端视角快速学习Maven
12 2
【前端学java】如何从前端视角快速学习Maven
|
8天前
|
前端开发 Oracle Java
【前端学java】java开发的依赖安装与环境配置(1)
【8月更文挑战第8天】java开发的依赖安装与环境配置
26 1
【前端学java】java开发的依赖安装与环境配置(1)
|
6天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
6天前
|
安全 前端开发 Java
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
在Web安全上下文中,源(Origin)是指一个URL的协议、域名和端口号的组合。这三个部分共同定义了资源的来源,浏览器会根据这些信息来判断两个资源是否属于同一源。例如,https://www.example.com:443和http://www.example.com虽然域名相同,但由于协议和端口号不同,它们被视为不同的源。同源(Same-Origin)是指两个URL的协议、域名和端口号完全相同。只有当这些条件都满足时,浏览器才认为这两个资源来自同一源,从而允许它们之间的交互操作。
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
|
5天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
6天前
|
IDE Java 开发工具
Java 开发神器 Lombok:告别冗余,拥抱优雅!
Java 开发神器 Lombok:告别冗余,拥抱优雅!
14 0
|
3月前
|
存储 安全 Java
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
59 1
|
3月前
|
存储 Java
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
|
3月前
|
Java 测试技术 C++
【JAVA学习之路 | 进阶篇】File类及常用方法
【JAVA学习之路 | 进阶篇】File类及常用方法