返回顶部
首页 > 资讯 > 后端开发 > Python >JavaListener监听器使用规范详细介绍
  • 560
分享到

JavaListener监听器使用规范详细介绍

JavaListener监听器JavaListenerJava监听器 2023-01-13 12:01:25 560人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录1、什么是监听器以及监听器作用2、Servlet规范中提供了哪些监听器3、实现一个监听器的步骤4、httpsessionBindingListener5、HttpSessionI

1、什么是监听器以及监听器作用

①监听器是Servlet规范中的一员。就像Filter一样。Filter也是Servlet规范中的一员。

②在Servlet中,所有的监听器接口都是以“Listener”结尾。

③监听器实际上是Servlet规范留给我们javaweb程序员的特殊时机。

④特殊的时刻如果想执行这段代码,你需要想到使用对应的监听器。

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

javax.servlet包下:

①ServletContextListener

②ServletContextAttributeListener

③ServletRequestListener

④ServletRequestAttributeListener

jakarta.servlet.http包下:

①HttpSessionListener

②HttpSessionAttributeListener

③HttpSessionBindingListener

④HttpSessionIdListener

⑤HttpSessionActivationListener

3、实现一个监听器的步骤

这里主要先讲解熟悉的关于三个域对象的监听器:

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;

// ServletContextListener监听器主要监听的是:ServletContext对象的状态。
public class MyServletContextListener implements ServletContextListener { // 服务器启动时间点
    
    @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;

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

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

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

@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");
    }
}

4、HttpSessionBindingListener

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

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;

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

?HttpSessionAttributeListener监听器

①该监听器是需要使用@WebListener注解进行标注的(或者使用web.xml文件进行配置)

②该监听器监听的是session域中数据的变化。只要数据变化,则执行相应的方法;主要监测点在session域对象上。

③监听的是session域,只要把数据放入session域就进行监听!

?HttpSessionBindingListener监听器

①该监听器是不需要使用@WebListener进行标注,类直接实现即可。

②假设User类实现了该监听器,那么User对象在被放入session的时候触发bind事件,User对象从session中删除的时候,触发unbind事件。

③假设Customer类没有实现该监听器,那么Customer对象放入session或者从session删除的时候,不会触发bind和unbind事件。

④监听的是普通的java对象,那个类实现了这个监听器,就监听那个类!

?总结

①对于HttpSessionAttributeListener监听的是任何种类的对象,只要放入session域当中就可以;上述user1和user2都可以触发!

②对于HttpSessionBindingListener监听的是特殊的对象,只有实现HttpSessionBindingListener接口的才可以;上述只有user1才能触发!

(4)那么这两个监听器有什么用呢?

我们通过一个简单的业务需求了解一下:

业务1:编写一个功能,记录该网站实时的在线用户的个数

我们可以通过服务器端有没有分配session对象,因为一个session代表了一个用户。有一个session就代表有一个用户。如果你采用这种逻辑去实现的话,session有多少个,在线用户就有多少个。这种方式的话:HttpSessionListener够用了。session对象只要新建,则count++,然后将count存储到ServletContext域当中,在页面展示在线人数即可!

业务2:只统计登录的用户的在线数量

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

5、HttpSessionIdListener&HttpSessionActivationListener

这两个监听器不常用,这里只简单了解即可:

(1)HttpSessionIdListener:session的id发生改变的时候,监听器中的唯一一个方法就会被调用。

(2)HttpSessionActivationListener:监听session对象的钝化和活化的。

①钝化:session对象从内存存储到硬盘文件。

②活化:从硬盘文件把session恢复到内存。

6、使用监听器统计网站在线人数

实现oa项目中当前登录在线的人数!

(1)什么代表着用户登录了?

?session.setAttribute("user", userObj); User类型的对象只要往session中存储过,表示有新用户登录。

(2)什么代表着用户退出了?

?session.removeAttribute("user"); User类型的对象从session域中移除了。

?或者有可能是session销毁了。(session超时) 。

(3)思考:我们要先思考一下寻访到什么域里面?

统计这个项目当汇总的登录在线人数,一个人一个的(session)以下的域肯定都不行,所以只能使用application域(ServletContext)。

①编写User类实现监听器的接口;然后修改关于所有session.getAttribute的代码

package com.bjpowernode.oa.bean;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class User implements HttpSessionBindingListener {
    // 重写两个方法
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        // 用户登录了
        // 相当于User类型的对象向session域当中存放
        // 获取application域对象
        // event.getSession()获取到session;在调用getServletContext()获取到域对象
        ServletContext application = event.getSession().getServletContext();
        // 获取到在线人数
        Object onlioncount = application.getAttribute("onlioncount");
        // 第一个用户登录,里面什么都没有,返回的是一个null
        if (onlioncount == null) {
            application.setAttribute("onlioncount",1);
        }else {
            // 直接 onlioncount++有问题,前面是Object类型,强转
            Integer count = (Integer)onlioncount;
            count++;
            // 在存入域当中
            application.setAttribute("onlioncount",count);
        }
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        // 用户退出了
        // 相当于User类型的对象向session域当中删除
        // 获取application域对象
        ServletContext application = event.getSession().getServletContext();
        // 获取域当中的数据,肯定不是空
        Integer onlioncount = (Integer) application.getAttribute("onlioncount");
        onlioncount--;
        // 在存入域当中
        application.setAttribute("onlioncount",onlioncount);
    }
    // 定义属性
    private String username;
    private String password;
    // 构造方法
    public User() {
    }
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    // setter and getter
    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;
    }
}

②修改UserServlet类和WelcomeServlet

// 把用户名放进session
session.setAttribute("username",username);
// 改为这样存
User user = new User(username, password);
session.setAttribute("user",user);

③修改过滤器LoginFilter

if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/dept/login".equals(servletPath) || "/dept/exit".equals(servletPath)
                || (session != null && session.getAttribute("username") != null)){
// username改为user,因为前面存储的名字变了
if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
                "/dept/login".equals(servletPath) || "/dept/exit".equals(servletPath)
                || (session != null && session.getAttribute("user") != null)){

④修改list.jsp页面

<h3>欢迎${username}登录</h3>
<!--修改为-->
<h3>欢迎${user.username}登录,在线人数${onlioncount}人</h3>

⑤最终达到的效果

假如开了两个浏览器,登录了两次

点击退出登录,刷新另一个浏览器的页面

到此这篇关于Java Listener监听器使用规范详细介绍的文章就介绍到这了,更多相关Java Listener监听器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: JavaListener监听器使用规范详细介绍

本文链接: https://lsjlt.com/news/177628.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JavaListener监听器使用规范详细介绍
    目录1、什么是监听器以及监听器作用2、Servlet规范中提供了哪些监听器3、实现一个监听器的步骤4、HttpSessionBindingListener5、HttpSessionI...
    99+
    2023-01-13
    Java Listener监听器 Java Listener Java监听器
  • JavaScript事件监听器详细介绍
    目录什么是事件1. 事件绑定2. 常见事件什么是事件 HTML 事件是发生在 HTML 元素上的“行为 ”。比如:页面上的 按钮被点击、鼠标移动到元素之上、按...
    99+
    2024-04-02
  • 关于java中变量命名规范的详细介绍
    Java是一种区分字母的大小写的语言,所以我们在定义变量名的时候应该注意区分大小写的使用和一些规范,接下来我们简单的来讲讲Java语言中包、类、变量等的命名规范。(一)Package(包)的命名Package的名字应该都是由一个小写单词组成...
    99+
    2019-10-05
    java入门 java 变量 命名规范 介绍
  • MySQL数据库命令和基本设计规范详细介绍
    本篇内容主要讲解“MySQL数据库命令和基本设计规范详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL数据库命令和基本设计规范详细介绍”吧!一、数...
    99+
    2024-04-02
  • Android 触摸事件监听(Activity层,ViewGroup层,View层)详细介绍
    Android不同层次的触摸事件监听       APP开发中,经常会遇到有关手势处理的操作,比如向右滑动返回上一个页面。关于...
    99+
    2022-06-06
    监听 事件 activity Android
  • 超详细MySQL使用规范分享
    最近涉及数据库相关操作较多,公司现有规范也不是太全面,就根据网上各路大神的相关规范,整理了一些自用的规范用法,万望指正。 数据库环境 dev: 开发环境 开发可读写,可修改表结构。开发人员可以修改表结构,可以随意修改...
    99+
    2022-05-26
    MySQL 规范 MySQL 使用规范
  • C++BoostMultiIndex使用详细介绍
    目录一、关于BOOST的容器二、Boost.MultiIndex练习一、关于BOOST的容器 容器是 C++ 中最有用的数据结构之一。标准库提供了许多容器,而 Boost 库提供的更...
    99+
    2022-11-13
    C++ Boost MultiIndex C++ MultiIndex
  • Android 模拟器的使用详细介绍
    让我们一起学习一下模拟器的使用。 本文内容如下: 模拟器和真机的比较 创建Android模拟器(emulator) 运行Android模拟器 设置简体中文语...
    99+
    2022-06-06
    模拟器 Android
  • ReentrantLock介绍及使用(超详细)
    点击 Mr.绵羊的知识星球 解锁更多优质文章。 目录 一、介绍 1. 简介 2. 是什么类型的锁 3. 优点 4. 原理 5. 主要方法 6. 使用时注意事项 二、实际应用 1. 案例一 2. 案例二 一、介绍 1. 简介     ...
    99+
    2023-09-20
    java 开发语言
  • fastjson 使用方法详细介绍
    Fastjson介绍Fastjson是一个Java语言编写的JSON处理器。遵循http://json.org标准,为其官方网站收录的参考实现之一。功能qiang打,支持JDK的各种类型,包括基本的JavaBean、Collection、M...
    99+
    2023-05-30
    fastjson 使用
  • TypeScript泛型使用详细介绍
    目录1 什么是泛型2 泛型方法3 泛型类4 泛型接口1 什么是泛型 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别...
    99+
    2022-11-13
    TypeScript泛型 TypeScript泛型使用方法
  • Android控件系列之Button以及Android监听器使用介绍
    学习目的: 1、掌握在Android中如何建立Button 2、掌握Button的常用属性 3、掌握Button按钮的点击事件(监听器) Button是各种UI中最常用的控件之...
    99+
    2022-06-06
    button Android
  • Vuex详细介绍和使用方法
    目录一、什么是Vuex二、运行机制三、创建项目1、使用脚手架搭建Vue项目2、安装Vuex3、启动项目4、配置使用Vuex4.1、创建store文件夹4.2、配置全局使用store对...
    99+
    2024-04-02
  • Java中ArrayList的使用详细介绍
    目录1.ArrayList类1.1ArrayList类概述1.2ArrayList类常用方法1.2.1构造方法1.2.2成员方法1.2.3示例代码1.3ArrayList存储字符串并...
    99+
    2024-04-02
  • Python 内置logging 使用详细介绍
    目录logging 的主要作用logging 日志等级logging 的基础函数logging 的四大组件(类)logging 的配置logging 和 print 的区别主要参考资...
    99+
    2024-04-02
  • 详细介绍Github的使用方法
    随着互联网技术的不断发展,越来越多的开发者开始加入到开源项目中,Github作为目前全球最大的代码托管平台之一,也成为了开发者们分享、学习、合作的重要工具之一。然而,如何使用Github来进行代码管理、版本控制、协作开发等,还是很多新手开发...
    99+
    2023-10-22
  • C++四种cast使用详细介绍
    目录一、static_cast1、基本数据类型转换2、指针和void指针的转换 3、父类和子类之间的转换二、dynamic_cast三、const_cast1、加上cons...
    99+
    2024-04-02
  • SpringMVC配置与使用详细介绍
    目录一、SpringMVC的使用1、MVC模式2、具体的坐标如下3、配置DispatcheServlet4、编写springmvc.xml的配置文件二、SpringMVC原理1、Sp...
    99+
    2024-04-02
  • SwiftExtension扩展得使用详细介绍
    目录扩展(Extension)协议与初始化器协议泛型扩展(Extension) 1、Swift中的扩展,有点类似于OC中的分类(Category) 2、扩展可以为枚举、结构体、类、协...
    99+
    2024-04-02
  • JetpackCompose布局的使用详细介绍
    目录一.标准布局组件二.修饰符三.滑动组件1.ScrollableRow和ScrollableColumn2.LazyRowFor和LazyColumnFor一.标准布局组件 Com...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作