从零开始学习JavaWeb - 过滤器和监听器详解

1. Filter原理

1.1 基本概念

  • Filter本意为”过滤“的含义,是JavaWeb的三大组件之一,三大组件为:Servlet、Filter、
    Listener。
  • 过滤器是向 Web 应用程序的请求和响应处理添加功能的 Web 服务组件。
  • 过滤器相当于浏览器与Web资源之间的一道过滤网,在访问资源之前通过一系列的过滤器对请求
    进行修改、判断以及拦截等,也可以对响应进行修改、判断以及拦截等

1.2 工作原理

image-20220112155207146

1.3 Filter使用方法

  1. 实现 Filter 接口

    package cn.knightzz.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class LoginFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("LoginFilter init ...");
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
            System.out.println("进入 LoginFilter => doFilter");
            chain.doFilter(request, response);
            System.out.println("离开 LoginFilter => doFilter");
        }
    
        @Override
        public void destroy() {
            System.out.println("LoginFilter destroy ...");
        }
    }
    
    
  2. web.xml 中配置

    • 这里需要特别注意 : 如果 url-pattern 配置失败,
      <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>cn.knightzz.filter.LoginFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/login</url-pattern>
      </filter-mapping>
    

1.4 Filter接口

javax.servlet.Filter接口主要用于描述过滤器对象,可以对资源的请求和资源的响应操作进行筛选
操作。

  • void init(FilterConfig filterConfig) 实现过滤器的初始化操作
  • void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) 执行过滤操作的功能
  • void destroy() 实现过滤器的销毁操作

1.5 FilterConfig接口

javax.servlet.FilterConfifig接口主要用于描述过滤器的配置信息

  • String getFilterName() 获取过滤器的名字

  • String getInitParameter(String name) 获取指定的初始化参数信息

  • Enumeration getInitParameterNames() 获取所有的初始化操作名称

  • ServletContext getServletContext() 获取 ServletContext 对象

  • 可以在 web.xml 中设置 并通过 init 方法的参数 FilterConfig 接口获取

    <filter>
        <filter-name>HtmlFilter</filter-name>
        <filter-class>cn.knightzz.filter.HtmlFilter</filter-class>
        <!-- 设置初始化参数 -->
        <init-param>
          <param-name>username</param-name>
          <param-value>root</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>HtmlFilter</filter-name>
        <url-pattern>*.html</url-pattern>
      </filter-mapping>
    
  • HtmlFilter

    public class HtmlFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
            System.out.println("HtmlFilter init ...");
            String filterName = filterConfig.getFilterName();
            System.out.println("filterName = " + filterName);
            String username = filterConfig.getInitParameter("username");
            System.out.println("InitParameter = " + username);
    
        }
     	// ....   
    }
    

1.6 多个过滤器

image-20220112162934431

  • 需要注意的是 : 当满足多个过滤条件是 过滤器的顺序是根据 web.xml 配置的顺序决定的

  • 主要请求路径满足 url-partten就会被对应的过滤器所拦截, 然后执行过滤器的 doFilter 方法

  • 以下面的代码为例 :

        @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("进入 HtmlFilter => doFilter ");
            chain.doFilter(request, response);
            System.out.println("离开 HtmlFilter => doFilter ");
       }
    
  • 上图的访问顺序如下

    1. 进入过滤器1, 执行 doFilter 里面 chain.doFilter(request, response); 之前的代码
    2. 执行 chain.doFilter(request, response); 放行到下一个过滤器2
    3. 进入过滤器2, 执行 doFilter 里面 chain.doFilter(request, response); 之前的代码
    4. 执行 chain.doFilter(request, response); 放行到下一个过滤器3
    5. 进入过滤器3, 执行 doFilter 里面 chain.doFilter(request, response); 之前的代码
    6. 执行 chain.doFilter(request, response); 放行到服务器
    7. 服务器执行 doPost 或者 doGet 方法
    8. 进入过滤器3, 执行 doFilter 里面 chain.doFilter(request, response); 之后的代码
    9. 进入过滤器2, 执行 doFilter 里面 chain.doFilter(request, response); 之后的代码
    10. 进入过滤器1, 执行 doFilter 里面 chain.doFilter(request, response); 之后的代码
    11. 返回到浏览器响应

1.7 过滤器的特点

  • 实现代码的“可插拔性”,即增加或减少某个功能模块,不会影响程序的正常执行。
  • 可以将多个相同处理逻辑的模块集中写在过滤器里面,可实现重复利用、也方便代码的维护。

2. Listern原理

2.1 监听器基本概念

  • Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。
  • 容器产生的事件分类如下:
    • 生命周期相关的事件。
    • 属性状态相关的事件。
    • 存值状态相关的事件。
    • 底层原理是采用接口回调的方式实现

2.2 监听器基本类型

image-20220112222735451

2.3 ServletRequestListener监听器

2.3.1 基本概念
  • ServletRequest创建和关闭时都会通知ServletRequestListener监听器。
2.3.2 常用方法
  • void requestInitialized(ServletRequestEvent sre) 实现ServletRequest对象的初始化
  • void requestDestroyed(ServletRequestEvent sre) 实现ServletRequest对象的销毁
2.3.3 代码示例
  • MyServletRequestListener

    package cn.knightzz.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    
    public class MyServletRequestListener implements ServletRequestListener {
    
    
        @Override
        public void requestDestroyed(ServletRequestEvent sre) {
            // 监听ServletRequest的销毁
            System.out.println("监听ServletRequest的销毁....");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent sre) {
            // 监听Servlet的初始化
            System.out.println("监听ServletRequest的初始化....");
        }
    }
    
    
  • web.xml 配置

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      
      <listener>
        <listener-class>cn.knightzz.listener.MyServletRequestListener</listener-class>
      </listener>
    </web-app>
    
    
  • MyServlet

    package cn.knightzz.servlet;
    
    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 java.io.IOException;
    
    /**
     * @author 王天赐
     * @title: HelloServlet
     * @projectName spring-aop-01
     * @description:
     * @website http://knightzz.cn/
     * @github https://github.com/knightzz1998
     * @date 2022/1/12 21:52
     */
    @WebServlet(name = "MyServlet", urlPatterns = "/my-servlet")
    public class MyServlet extends HttpServlet {
    
    
        @Override
        public void init() throws ServletException {
            System.out.println("MyServlet init ...");
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet doPost ...");
        }
    
        @Override
        public void destroy() {
            // Tomcat 服务器关闭时, Servlet对象才会销毁
            System.out.println("MyServlet destroy ...");
        }
    }
    
    
2.3.4 执行结果
监听ServletRequest的初始化....
MyServlet init ...
MyServlet doPost ...
监听ServletRequest的销毁....

2.4 ServletRequestAttributeListener

2.4.1 基本概念
  • ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器。
2.4.2 常用方法
  • void attributeAdded(ServletRequestAttributeEvent srae) 增加属性时触发
  • void attributeReplaced(ServletRequestAttributeEvent srae) 修改属性时触发
  • void attributeRemoved(ServletRequestAttributeEvent srae) 删除属性时触发
2.4.3 代码示例
  • MyServletRequestAttributeListener

    package cn.knightzz.listener;
    
    import javax.servlet.ServletRequestAttributeEvent;
    import javax.servlet.ServletRequestAttributeListener;
    
    
    public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
    
        @Override
        public void attributeAdded(ServletRequestAttributeEvent srae) {
            String name = srae.getName();
            System.out.println("监听 " + name + " 属性的增加...");
        }
    
        @Override
        public void attributeRemoved(ServletRequestAttributeEvent srae) {
            String name = srae.getName();
            System.out.println("监听 " + name + " 属性的移除...");
        }
    
        @Override
        public void attributeReplaced(ServletRequestAttributeEvent srae) {
            String name = srae.getName();
            System.out.println("监听 " + name + " 属性的替换...");
        }
    }
    
    
  • web.xml 中配置

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      
      <listener>
        <listener-class>cn.knightzz.listener.MyServletRequestListener</listener-class>
      </listener>
    
      <listener>
        <listener-class>cn.knightzz.listener.MyServletRequestAttributeListener</listener-class>
      </listener>
    </web-app>
    
    
2.4.4 执行结果
监听ServletRequest的初始化....
MyServlet init ...
监听 org.apache.catalina.ASYNC_SUPPORTED 属性的替换...
MyServlet doPost ...
监听 username 属性的增加...
监听 username 属性的替换...
监听 username 属性的移除...
监听ServletRequest的销毁....

2.5 HttpSessionListener

2.5.1 基本概念
  • 当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听
    器。
2.5.2 常用方法
  • void sessionCreated(HttpSessionEvent se) 当一个HttpSession对象被创建时会调用这个方法
  • void sessionDestroyed(HttpSessionEvent se) 当一个HttpSession超时或者调用HttpSession的 invalidate() 方法让它销毁时,将会调用这个方法
2.5.3 代码示例
  • MyHttpSessionListener

    package cn.knightzz.listener;
    
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class MyHttpSessionListener implements HttpSessionListener {
    
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            System.out.println("创建 Session 监听 ...");
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            System.out.println("销毁 Session 监听 ...");
        }
    }
    
    
  • MyServlet

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet doPost ...");
            req.setAttribute("username", "root");
            req.setAttribute("username", "2068");
            req.removeAttribute("username");
    
            HttpSession session = req.getSession(true);
            System.out.println("创建 Session ... ");
        }
    
  • web.xml

      <listener>
        <listener-class>cn.knightzz.listener.MyHttpSessionListener</listener-class>
      </listener>
    
2.5.4 执行结果
监听 username 属性的增加...
监听 username 属性的替换...
监听 username 属性的移除...
创建 Session 监听 ...
创建 Session ... 
监听ServletRequest的销毁....

2.6 HttpSessionAttributeListener

2.6.1 基本概念
  • HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监听器
2.6.2 常用方法

image-20220113205801068

2.6.3 代码示例
  • MyHttpSessionAttributeListener

    package cn.knightzz.listener;
    
    import javax.servlet.http.HttpSessionAttributeListener;
    import javax.servlet.http.HttpSessionBindingEvent;
    
    /**
     * @author 王天赐
     * @title: MyHttpSessionAttributeListener
     * @projectName spring-aop-01
     * @description:
     * @website http://knightzz.cn/
     * @github https://github.com/knightzz1998
     * @date 2022/1/13 20:45
     */
    public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    
        @Override
        public void attributeAdded(HttpSessionBindingEvent event) {
            System.out.println("监听 Session 添加 Attribute");
        }
    
        @Override
        public void attributeRemoved(HttpSessionBindingEvent event) {
            System.out.println("监听 Session 移除 Attribute");
        }
    
        @Override
        public void attributeReplaced(HttpSessionBindingEvent event) {
            System.out.println("监听 Session 添加 Attribute");
        }
    }
    
    
  • web.xml

  <listener>
    <listener-class>cn.knightzz.listener.MyHttpSessionAttributeListener</listener-class>
  </listener>
2.6.4 执行结果
监听 username 属性的增加...
监听 username 属性的替换...
监听 username 属性的移除...
创建 Session 监听 ...
创建 Session ... 
监听 Session 添加 Attribute
监听 Session 添加 Attribute
监听 Session 移除 Attribute
监听ServletRequest的销毁....

2.7 ServletContextListener

2.7.1 基本概念
  • 在ServletContext创建和关闭时都会通知ServletContextListener监听器。
2.7.2 常用方法
  • void contextInitialized(ServletContextEvent sce)
    当ServletContext创建的时候,将会调用这个方法
  • void contextDestroyed(ServletContextEvent sce)
    当ServletContext销毁的时候(例如关闭应用服务器 或者重新加载应用),将会调用这个方法
2.7.3 代码示例
package cn.knightzz.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Servlet Context 初始化 ... ");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Servlet Context 销毁 ... ");
    }
}

2.7.4 执行结果
  • Tomact服务器在启动的时候会自动创建 ServletContext 对象, 在关闭的时候销毁

2.8 ServletContextAttributeListener

2.8.1 基本概念
  • 向ServletContext添加、删除或者替换一个属性的时候,将会通知 ServletContextAttributesListener 监听器
2.8.2 常用方法
  • void attributeAdded(ServletContextAttributeEvent scae) 往ServletContext中加入一个属性的时候触发
  • void attributeRemoved(ServletContextAttributeEvent scae) 从ServletContext中删除一个属性的时候触发
  • void attributeReplaced(ServletContextAttributeEvent scae) 改变ServletContext中属性的时候触发
2.8.3 代码示例
  • MyServletContextAttributeListener

    package cn.knightzz.listener;
    
    import javax.servlet.ServletContextAttributeEvent;
    import javax.servlet.ServletContextAttributeListener;
    
    
    public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    
        @Override
        public void attributeAdded(ServletContextAttributeEvent event) {
            System.out.println("监听 Servlet Context 属性添加");
        }
    
        @Override
        public void attributeRemoved(ServletContextAttributeEvent event) {
            System.out.println("监听 Servlet Context 属性移除");
        }
    
        @Override
        public void attributeReplaced(ServletContextAttributeEvent event) {
            System.out.println("监听 Servlet Context 属性替换");
        }
    }
    
    
  • MyServlet

    package cn.knightzz.servlet;
    
    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;
    
    /**
     * @author 王天赐
     * @title: HelloServlet
     * @projectName spring-aop-01
     * @description:
     * @website http://knightzz.cn/
     * @github https://github.com/knightzz1998
     * @date 2022/1/12 21:52
     */
    @WebServlet(name = "MyServlet", urlPatterns = "/my-servlet")
    public class MyServlet extends HttpServlet {
    
    
        @Override
        public void init() throws ServletException {
            System.out.println("MyServlet init ...");
        }
    
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet doPost ...");
            req.setAttribute("username", "root");
            req.setAttribute("username", "2068");
            req.removeAttribute("username");
    
            HttpSession session = req.getSession(true);
            System.out.println("创建 Session ... ");
    
            session.setAttribute("name", "TOM");
            session.setAttribute("name", "TOM");
            session.removeAttribute("name");
    
            // 获取ServletContext
            ServletContext servletContext = this.getServletContext();
            servletContext.setAttribute("param", "TSK");
            servletContext.setAttribute("param", "2022");
            servletContext.removeAttribute("param");
        }
    
        @Override
        public void destroy() {
            // Tomcat 服务器关闭时, Servlet对象才会销毁
            System.out.println("MyServlet destroy ...");
        }
    }
    
    
  • web.xml

      <listener>
        <listener-class>cn.knightzz.listener.MyServletContextAttributeListener</listener-class>
      </listener>
    
2.8.4 执行结果
监听 Servlet Context 属性添加
监听 Servlet Context 属性替换
监听 Servlet Context 属性移除

2.9 HttpSessionBindingListener

2.9.1 基本概念
  • HttpSession中绑定对象和解除绑定对象时,将会通知HttpSessionListener监听器。
  • 需要继承 HttpSessionBindingListener
2.9.2 常用方法
  • void valueBound(HttpSessionBindingEvent event) 有对象绑定时调用该方法
  • void valueUnbound(HttpSessionBindingEvent event) 有对象解除绑定时调用该方法
2.9.3 代码示例
  • Person :需要继承 HttpSessionBindingListener 不需要配置 web.xml

    package cn.knightzz.entity;
    
    import javax.servlet.http.HttpSessionBindingEvent;
    import javax.servlet.http.HttpSessionBindingListener;
    
    
    public class Person implements HttpSessionBindingListener {
    
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public void valueBound(HttpSessionBindingEvent event) {
            System.out.println("监听 Session 对象 绑定");
        }
    
        @Override
        public void valueUnbound(HttpSessionBindingEvent event) {
            System.out.println("监听 Session 对象 解绑定");
        }
    }
    
    
  • MyServlet

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet doPost ...");
            req.setAttribute("username", "root");
            req.setAttribute("username", "2068");
            req.removeAttribute("username");
    
            HttpSession session = req.getSession(true);
            System.out.println("创建 Session ... ");
    
            session.setAttribute("name", "TOM");
            session.setAttribute("name", "TOM");
            session.removeAttribute("name");
    
            // 获取ServletContext
            ServletContext servletContext = this.getServletContext();
            servletContext.setAttribute("param", "TSK");
            servletContext.setAttribute("param", "2022");
            servletContext.removeAttribute("param");
    
            // 定义Session绑定属性
            Person person = new Person();
            person.setAge(18);
            person.setName("KSF");
            session.setAttribute("person", person);
    
        }
    
2.9.4 执行结果
监听 username 属性的增加...
监听 username 属性的替换...
监听 username 属性的移除...
创建 Session 监听 ...
创建 Session ... 
监听 Session 添加 Attribute
监听 Session 添加 Attribute
监听 Session 移除 Attribute
监听 Servlet Context 属性添加
监听 Servlet Context 属性替换
监听 Servlet Context 属性移除
监听 Session 对象 绑定
监听 Session 添加 Attribute
监听ServletRequest的销毁....

2.10 HttpSessionActivationListener

2.10.1 基本概念
  • 当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
  • 钝化也叫持久化, 因为Session数据是存储在服务器内存中的, 服务器关闭的时候需要把session保存成文件存储在硬盘上
  • 活化就是将数据从硬盘上读取出来到内存的过程
2.10.2 常用方法
  • void sessionWillPassivate(HttpSessionEvent se) 有钝化操作时调用该方法
  • void sessionDidActivate(HttpSessionEvent se) 有活化操作时调用该方法
2.10.3 代码示例
  • Student 类 需要实现 Serializable, HttpSessionActivationListener

    package cn.knightzz.entity;
    
    import javax.servlet.http.HttpSessionActivationListener;
    import javax.servlet.http.HttpSessionEvent;
    import java.io.Serializable;
    
    public class Student implements Serializable, HttpSessionActivationListener {
    
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public void sessionWillPassivate(HttpSessionEvent se) {
            System.out.println(" 将Session信息保存到本地 ... ");
        }
    
        @Override
        public void sessionDidActivate(HttpSessionEvent se) {
            System.out.println(" 将Session文件从本地读取到内存中 ... ");
        }
    }
    
    
  • MyServlet

    @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet doPost ...");
            req.setAttribute("username", "root");
            req.setAttribute("username", "2068");
            req.removeAttribute("username");
    
            HttpSession session = req.getSession(true);
            System.out.println("创建 Session ... ");
    
            session.setAttribute("name", "TOM");
            session.setAttribute("name", "TOM");
            session.removeAttribute("name");
    
            // 获取ServletContext
            ServletContext servletContext = this.getServletContext();
            servletContext.setAttribute("param", "TSK");
            servletContext.setAttribute("param", "2022");
            servletContext.removeAttribute("param");
    
            // 定义Session绑定属性
            Person person = new Person();
            person.setAge(18);
            person.setName("KSF");
            session.setAttribute("person", person);
    
            Student student = new Student();
            student.setAge(18);
            student.setName("KSF");
            session.setAttribute("student", student);
        }
    
2.10.4 执行结果
MyServlet destroy ...
 将Session信息保存到本地 ... 
监听 Session 对象 解绑定
监听 Session 移除 Attribute
Servlet Context 销毁 ... 
2.10.5 配置文件持久化路径
  • 配置 context.xml , 这个文件存在 Tomact服务器的 conf 目录下, 在文件里添加如下内容即可

    <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true"> <!-- 配置文件存放的路径信息,可以自由指定 --> <Store className="org.apache.catalina.session.FileStore" directory="C:\session"/> </Manager>
    

3. 在线用户数量统计

3.1 原理解析

  • 每个浏览器访问服务器都会创建一个 Session 对象, 这样Session的创建和销毁可以表示用户在线和下线
  • 而一个服务器只会创建一个ServletContext对象
  • 当新的Session创建的时候, 将当前的在线人数加1, 并存储在ServletContext对象上

3.2 代码案例

  • OnlineUser 需要实现 HttpSessionListener, ServletContextListener 接口

    package cn.knightzz.entity;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class OnlineUser implements HttpSessionListener, ServletContextListener {
    
        ServletContext context = null;
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            this.context = sce.getServletContext();
            context.setAttribute("onlineUser", 0);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            this.context = null;
        }
    
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            Integer onlineUser = (Integer) context.getAttribute("onlineUser");
            context.setAttribute("onlineUser", onlineUser + 1);
            System.out.println("新增在线人数 1 人, 当前在线人数 : " + (onlineUser + 1));
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            Integer onlineUser = (Integer) context.getAttribute("onlineUser");
            context.setAttribute("onlineUser", onlineUser - 1);
            System.out.println("下线人数 1 人, 当前在线人数 : " + (onlineUser - 1));
        }
    }
    
    
  • 需要在 web.xml 中配置

      <listener>
        <listener-class>cn.knightzz.entity.OnlineUser</listener-class>
      </listener>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兀坐晴窗独饮茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值