JavaWeb-Listener

什么是监听器:

  • 监听器是Servlet规范中的一员,就像Filter一样,Filter也是Servlet规范中的一员。
  • 在Servlet中,所有监听器接口都是以“Listener”结尾。

监听器有什么用:

  • 监听器实际上是Servlet规范留给我们javaweb程序员的特殊时机。
  • 特殊的时刻如果想执行这段代码,你需要想到使用对应的监听器。

Servlet规范中提供了哪些监听器:

jakarta.servlet包下:

  • ServletContextListener
  • ServletContextAttributeListener
  • ServletRequestListener
  • ServletRequestAttributeListener

jakarta.servlet.http包下:

  • HttpSessionListener
  • HttpSessionAttributeListener
  • HttpSessionBindingListener
  • HttpSessionActivationListener

实现一个监听器的步骤:以ServletContextListener为例:

第一步:编写一个类实现ServletContextListener接口,并实现里面的方法

void contextInitialized(ServletContextEvent sce)
void contextDestroyed(ServletContextEvent sce)

第二步:在web.xml文件中对ServletContextListener进行配置,如下:

    <listener>
        <listener-class>com.itzw.javaweb.listener.MyServletContextListener</listener-class>
    </listener>

当然也可以使用注解:@WebListener

注意:所有监听器都是不需要javaweb程序员调用的,由服务器负责调用,什么时候被调用呢?当某个特殊的事件发生之后,被web服务器调用。

经过测试,我们发现,监听器和域的声明周期一样,其中初始方法和销毁方法的执行时刻和他们对应的域的执行时刻是一样的,比如context监听器在服务器启动时执行,在服务器关闭时销毁;再比如request对应的监听器在每次请求时就执行一次初始和销毁。

package com.itzw.javaweb.listener;

import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;

@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("HttpSessionListener被创建了");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("HttpSessionListener被销毁了");
    }
}

AttributeListener

在执行相关的代码的时候它们的方法就会执行,比如HttpSessionAttributeListener

package com.itzw.javaweb.listener;

import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionBindingEvent;

@WebListener
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    @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被代替了");
    }
}

如上:在session被添加信息、代替、删除的时候会调用这几个方法。其它也是同理。

BindingListener

  • 该监听器不需要使用@WebListener进行标注
  • 假设User类实现了该监听器,那么User对象在被放入session的时候触发bind事件,User对象从session中删除的时候,触发unbind事件;假设Customer没有实现该监听器,那么Customer对象放入或者从session中删除的时候,不会触发bind和unbind事件。
  • 注意和AttributeListener区分开:AttributeListener需要@WebListener,它是只要有内容放入session或者别的操作都会触发AttributeListener。大致可以理解为,一个局部一个全局,一个范围小一个范围大

思考一个业务场景:

  • 编写一个功能,记录该网站实时的在线用户的个数。
  • 我们可以通过服务器有没有分配session对象,因为一个session代表了一个用户,这种情况HttpSessionListener就够用了。

业务发生变化,只统计登录的用户的在线人数:

  • session.setAttribute("user",userObj);
  • 用户登录的标志是什么?session中曾经存储过User类型的对象,那么这个时候可以让User类型的对象实现HttpSessionBindingListener监听器,只要User类型对象存储到session域中,则cout++,然后count++存储到ServletContext中,页面展示在线人数即可。

改造oa项目:添加在线人数功能:

根据上面的要求,创建一个User类:

package com.itzw.oa.bean;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;

public class User implements HttpSessionBindingListener {

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        //获取ServletContext对象
        ServletContext application = event.getSession().getServletContext();
        //获取在线人数
        Object onlineCount = application.getAttribute("onlineCount");
        if (onlineCount == null){
            application.setAttribute("onlineCount",1);
        }else {
            int count = (Integer)onlineCount;
            count++;
            application.setAttribute("onlineCount",count);
        }
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        //用户退出了
        //User类型的对象从session域中删除了
        ServletContext application = event.getSession().getServletContext();
        Integer onlineCount = (Integer) application.getAttribute("onlineCount");
        onlineCount--;
        application.setAttribute("onlineCount",onlineCount);
    }

    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    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;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

接下来,要对之前的代码进行一丢丢的修改,把用户名和密码装进这新创建的User类即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值