61监听器

news2024/11/16 9:53:09

监听器

概念

监听器用于监听web应用中某些对象信息的创建、销毁、增加,修改,删除等动作的

发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用

监听器对象中的方法。

常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等。

创建步骤

  1. 创建类
  2. 实现指定的监听器接口中的方法
  3. 在web.xml文件中配置监听或在类上标注@WebListener 注解

第一类:域对象监听器

监听域对象 创建与销毁的监听器

监听器接口描述
ServletContextListener监听Servlet上下文对象的创建、销毁
HttpSessionListener监听会话对象的创建、销毁
ServletRequestListener监听请求对象的创建、销毁
1.请求对象的创建和销毁的监听器

生命周期:

创建:客户端发送请求,Tomcat会创建请求对象

销毁:服务器返回响应,Tomcat会将请求对象销毁

public class MyServletRequestListener implements ServletRequestListener {

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {

        //获取请求对象
        ServletRequest request = servletRequestEvent.getServletRequest();

        System.out.println("请求对象被创建了:" + request);
    }

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {

        //获取请求对象
        ServletRequest request = servletRequestEvent.getServletRequest();

        System.out.println("请求对象被销毁了:" + request);
    }
}

<!-- web.xml中配置 -->
    <listener>
        <listener-class>com.ckl.listener.MyServletRequestListener</listener-class>
    </listener>

实验:再写两个页面html,jsp类型,启动服务器多次访问
请求对象可以存临时数据,存在时间短
在这里插入图片描述

2.全局域对象的创建和销毁的监听器

生命周期:

创建:项目启动时

销毁:服务器正常关闭时

经验:让整个项目共享的数据可以存储在全局域对象里

public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        ServletContext servletContext = servletContextEvent.getServletContext();

        //获取全局域对象的初始化参数 -- 注意:在web.xml中配置
        String code = servletContext.getInitParameter("code");
        System.out.println("全局域对象被创建了:" + servletContext + " -- " + code);

        //设置网站在线人数【共享】
        servletContext.setAttribute("count",0);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

        ServletContext servletContext = servletContextEvent.getServletContext();
        System.out.println("全局域对象被销毁了:" + servletContext);
    }
}
<!-- web.xml中配置 -->
<!--配置全局域对象的初始化参数-->
    <context-param>
        <param-name>code</param-name>
        <param-value>UTF-8</param-value>
    </context-param>

    <listener>
        <listener-class>com.qf.listener01.MyServletContextListener</listener-class>
    </listener>
3.会话对象的创建和销毁的监听器

生命周期:

创建:服务端使用到会话对象才会被创建

销毁:会话域对象过期时间到后会被销毁

注意:
1.客户端访问服务器里的html页面不会创建会话对象,因为没有使用到session
2.客户端访问服务器里的jsp页面会创建会话对象,因为使jsp里9大内置对象里有session
3.会话域对象过期时间默认30分钟
4.在web.xml中可以设置session的过期时间(时间单位:分钟),注意:最后一次使用session的时间往后移(闲置时间)

经验:

session对象在服务器中存储,默认30分钟过期时间

JSESSIONID存储在客户端的Cookie中,默认过期时间是会话结束时

这样会导致,关闭客户端后,session对象还存活在服务端,相同的客户端再次开启并发送请求访问session时就会创建新的session对象,原有的session对象就视作为占用资源的无效对象

我们可以设置JSESSIONID的过期时间,用户关闭客户端再次开启后才能找到之前在服务器对应的session对象

public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {

        HttpSession session = httpSessionEvent.getSession();
        System.out.println("会话域对象被创建了:" + session.getId());

        //获取全局域对象
        ServletContext servletContext = session.getServletContext();
        //更新网站在线人数
        int count = (Integer) servletContext.getAttribute("count");
        count++;
        servletContext.setAttribute("count",count);
        System.out.println(count);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("会话域对象被销毁了:" + session.getId());

        //获取全局域对象
        ServletContext servletContext = session.getServletContext();
        //更新网站在线人数
        int count = (Integer) servletContext.getAttribute("count");
        count--;
        servletContext.setAttribute("count",count);
        System.out.println(count);
    }
}
<!-- web.xml中配置 -->
    <listener>
        <listener-class>com.qf.listener01.MyHttpSessionListener</listener-class>
    </listener>
	<!--设置过期时间-->
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

第二类:属性监听器

监听域对象属性变化的监听器

监听器接口描述
ServletContextAttributeListener监听Servlet上下文对象属性的创建、删除、替换
HttpSessionAttributeListener监听会话对象属性的创建、删除、替换
ServletRequestAttributeListener监听请求对象属性的创建、删除、替换

Servlet上下文对象属性变化的监听器,其他同理实现接口生成方法

注意配置方式,注解用@WebListener

@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {

        ServletContext servletContext = servletContextAttributeEvent.getServletContext();
        String name = servletContextAttributeEvent.getName();
        Object value = servletContextAttributeEvent.getValue();
        System.out.println(servletContext + "全局域中的属性添加了:" + name + " -- " + value);
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        ServletContext servletContext = servletContextAttributeEvent.getServletContext();
        String name = servletContextAttributeEvent.getName();
        Object value = servletContextAttributeEvent.getValue();
        System.out.println(servletContext + "全局域中的属性删除了:" + name + " -- " + value);
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {

        ServletContext servletContext = servletContextAttributeEvent.getServletContext();
        String name = servletContextAttributeEvent.getName();
        Object value = servletContextAttributeEvent.getValue();//获取被替换的值
        System.out.println(servletContext + "全局域中的属性替换了:" + name + " -- " + value);
    }
}

不同在于域对象名字不同application,request、session,其他调用都与获取的相同,其中session可以获取id

    <%
        //操作全局域对象的属性
        application.setAttribute("msg","aaa");//添加属性
        application.setAttribute("msg","bbb");//替换属性
        application.removeAttribute("msg");//删除属性
    %>

第三类:监听HttpSession中的对象(JavaBean)

前两类监听器是作用在 ServletContext HttpSession ServletRequest上

第三类监听器是作用在JavaBean上的。

注意:这类监听器不需要在web.xml中配置

监听器接口描述
HttpSessionBindingListener监听会话对象中JavaBean对象的绑定、删除
HttpSessionActivationListener监听会话对象中JavaBean对象的钝化、活化

钝化(序列化):在内存中JavaBean对象通过Session存储硬盘的过程

活化(反序列化):从硬盘中通过Session取出JavaBean对象到内存的过程

1.理解

HttpSessionBindingListener

理解:监听该类(User)对象在session中的绑定(添加)和解绑(删除)

valueBound – 绑定方法

valueUnbound – 解绑方法

HttpSessionActivationListener

理解:监听该类(User)对象在session中的钝化(序列化)和活化(反序列化)

sessionWillPassivate – 钝化(序列化):将类(User)对象写入到文件

sessionDidActivate – 活化(反序列化):将文件里的对象读取到程序中

注意:

实现session的钝化和活化底层使用到了ObjectInputStream、ObjectOutputStream

钝化和活化的JavaBean对象必须实现Serializable(序列化接口)

注意: 想要随着Session 被钝化、活化的对象它的类必须实现Serializable 接口,放在

Session中没有实现Serilizable接口的对象,在Session钝化时,不会被序列化到磁盘上。


public class User implements HttpSessionBindingListener, HttpSessionActivationListener, Serializable {

    private String username;
    private transient String password;//transient修饰,不会被写到硬盘
    private String name;

//生成方法略
    
    @Override
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {

        HttpSession session = httpSessionBindingEvent.getSession();
        String name = httpSessionBindingEvent.getName();
        Object value = httpSessionBindingEvent.getValue();

        System.out.println(session.getId() + "会话对象中绑定了:" + name + " -- " + value);
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
        HttpSession session = httpSessionBindingEvent.getSession();
        String name = httpSessionBindingEvent.getName();
        Object value = httpSessionBindingEvent.getValue();

        System.out.println(session.getId() + "会话对象中解绑了:" + name + " -- " + value);
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {

        HttpSession session = httpSessionEvent.getSession();
        System.out.println(session.getId() + "的User对象被钝化了:" + this);
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println(session.getId() + "的User对象被活化了:" + this);
    }
}

当对象被绑定到HttpSession对象中时,web服务器调用该对象的valueBound方法

当对象从HttpSession对象中解除绑定时,web服务器调用该对象的valueUnbound方法

javabean对象将要随Session对象被钝化(序列化)之前,web服务器调用该对象的sessionWillPassivate 方法

这样javabean对象就可以知道自己将要和Session对象一起被钝化到硬盘中

javabean对象将要随Session对象被活化(反序列化)之后,web服务器调用该对象的sessionDidActive方法

这样javabean对象就可以知道自己将要和Session对象一起被活化回到内存中

<%@ page import="com.ckl.listener03.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>page02.jsp</h1>

        <%
            session.setAttribute("user",new User("qnz","123","奇男子"));
//            session.removeAttribute("user");

            //session还可以添加其他数据
            session.setAttribute("obj",new Object());
            session.setAttribute("msg","胡子");
        %>

</body>
</html>

序列化测试还需在WebContent\META-INF文件夹下创建一个context.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Context>
	<!-- 
		maxIdleSwap:"1": session如果1分钟没有使用就序列化
		directory: 序列化后文件所保存的路径 
	-->
	<Manager className="org.apache.catalina.session.PersistentManager"
		maxIdleSwap="1">
		<Store className="org.apache.catalina.session.FileStore" 		
			directory="C:\\text" />
	</Manager>
</Context>	
2.面试题
面试题1

Session中的JavaBean对象什么情况下会钝化

session未过期

JavaBean对象所属的类必须实现Serializable接口

服务器正常关闭

以上三个条件必须都满足

面试题2

Session中的JavaBean对象什么情况下不会钝化

1.session对象过期

2.session.invalidate();

3.服务器非正常关闭

以上三个条件满足一个即可

面试题3

Session中的JavaBean对象什么情况下不会活化

服务器启动,但是session对象过期了

解释

Session 的钝化与活化

  • 钝化:当服务器正常关闭时,还存活着的session(在设置时间内没有销毁) 会随着服务

器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下,这个过程叫

做Session 的钝化。

  • 活化:当服务器再次正常开启时,服务器会找到之前的“SESSIONS.ser” 文件,从中恢

复之前保存起来的Session 对象,这个过程叫做Session的活化。

  • 注意事项
  1. 想要随着Session 被钝化、活化的对象它的类必须实现Serializable 接口,还有的是只有在服务器正常关闭的条件下,还未超时的Session 才会被钝化成文件。当Session 超时、调用invalidate方法或者服务器在非正常情况下关闭时,Session 都不会被钝化,因此也就不存在活化。
  2. 在被钝化成“SESSIONS.ser” 文件时,不会因为超过Session 过期时间而消失,这个文件会一直存在,等到下一次服务器开启时消失。
  3. 当多个Session 被钝化时,这些被钝化的Session 都被保存在一个文件中,并不会为每个Session 都建立一个文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hbase 综合实验

1、设计表保存通话记录信息&#xff0c;实现相关查询功能 创建ua50tel表&#xff0c;并插入数据&#xff08;实训报告中‘&#xff1a;’存在于表中但会识别为语法所以在此不使用&#xff09; 依次重复上面的过程按实际输入&#xff0c;并查看表的内容 查询某人当月通话记录 …

内网电脑如何通过外网IP访问内网的服务器

内网的电脑&#xff0c;如何使用公网IP访问内网的服务器&#xff1f;写下这个标题&#xff0c;连我自己都学得拗口&#xff0c;可是又想不到更合适的标题。 正常来说&#xff0c;内网的电脑访问内网的服务器&#xff0c;当然是使用服务器的内网IP地址和端口&#xff0c;比如说&…

建立的Qsys系统变成Symbol Files

1.Platform Designer下&#xff0c;点击Generate 2.

C++数组全面讲解

文章目录 数组介绍数组的特点数组的优缺点数组和其他数据结构的比较 静态数组与动态数组的详细讲解一、静态数组1. 一维数组声明与初始化注意事项特点 2. 二维数组声明与初始化注意事项特点 3. 三维数组声明与初始化注意事项特点 二、动态数组1. 一维数组声明与初始化注意事项特…

HarmonyOS鸿蒙开发学习:鸿蒙基础-基础环境-ArkTS-组件-样式

鸿蒙基础-基础环境-ArkTS-组件-样式 DevEcoStudio编辑器下载链接 链接: https://pan.baidu.com/s/18C9i35YPh4GsHpbSif8KQw?pwdd6e9 提取码: d6e9 安装教程 下载对应的版本 windowsmac英特尔mac Arm API12 的编辑器 API12的模拟器(mac英特尔安装API11) Mac Arm芯片版本安装…

CCPC 2024, Shanghai

2024.8.5 12:00————17:00 CCPC 2024, Shanghai [A - 无线网络整点栅格统计](https://atcoder.jp/contests/math-and-algorithm/tasks/abc204_d?langen)[E - 无线软件日](https://atcoder.jp/contests/abc265/tasks/abc265_a?langen)[J - 极简合数序列](https://atcoder.…

【面试题】合井K个升序链表

合井K个升序链表 仅供面试学习 给定一个链表数组&#xff0c;每个链表都已经按升序排列。将所有链表合并到一个升序链表中&#xff0c;并返回合并后的链表。以下是详细的解题步骤和 Python 代码示例。 一、问题描述 将多个升序链表合并为一个升序链表。要求算法能有效处理链表…

Codeforces Round 871 (Div. 4)(A~H)

比赛链接 Dashboard - Codeforces Round 871 (Div. 4) - Codeforces A. Love Story 找到与codeforces 有多少个不同的字符。 #include<bits/stdc.h> #define int long long #define TEST int T; cin >> T; while (T--) #define ios ios::sync_with_stdio(fals…

人大金仓安装图文

1.下载 通过百度网盘分享的文件&#xff1a;人大金仓安装图文 链接&#xff1a;https://pan.baidu.com/s/1imt0KsyVXQALp_icEMoDpQ 提取码&#xff1a;zwef --来自百度网盘超级会员V3的分享 2.安装

CTFHub~RCE远程代码执行

0X01eval执行 # 进来我们直接看到了代码&#xff0c;大致意思就是传入一个参数cmd# 所以我们直接使用蚁剑进行连接&#xff0c;看一下能否成功# 接下来我们直接找出flag0X02文件包含 # 打开页面发现一大堆代码 大体意思是如果file中没有flag字符串就执行下面的include $_GET[…

【linux深入剖析】线程控制 | 多线程

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. 创建线程2. POSIX线程…

基于Kubernetes v1.25.0和Docker部署高可用集群(说明篇)

目录描述 Kubernetes组件说明 特定接口CRI、CNI、CSI Kubernetes v1.25集群创建方案选择 一、Kubernetes组件说明 Docker 的运行机制 运行机制详解&#xff1a; docker client&#xff1a;命令行输入的docker命令就是一个docker客户端 docker Engine&#xff1a;Engine也…

Java: 死锁问题详解(5000字)

文章目录 死锁的出现场景1. 一个线程一把锁,这个线程针对这把锁,连续加锁了两次2. 两个线程,两把锁3. N个线程 , M个锁4. 内存可见性为什么会出现内存可见性问题呢?解决方法 volatile关键字 总结synchronized:死锁的四个必要条件(缺一不可)[重点]:内存可见性问题: 死锁的出现场…

PCL安装与配置(PCL1.9.1+MSVC2017)

为了和我的VS的版本VS 2017对应&#xff0c;PCL下载的也是msvc_2017,PCL msvc2017最新的则是1.901版本&#xff0c;我们就以PCL 1.9.1为例了。&#xff08;如果你的vs是2019和2022&#xff0c;一定要注意PCL的版本&#xff09;。 一、下载PCL 我们打开PCL的github下载地址&am…

GDB调试器

GDB调试器 GDB的主要功能 常见命令 3、实战 1、生成能调试的执行文件&#xff08;一定要加-g&#xff09; 第一个是不能调试的 第二个这样加了-g才能进行调试 如果没加-g 执行gdb 执行文件&#xff08;会报下面这个 &#xff09; 像这样才是正常的 执行 gdb a_yes_g 这…

SSM计算机组成原理课程平台-计算机毕设定制-附项目源码(可白嫖)50168

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

金融行业到底该选择什么样的FTP替代方案?

2018年以来&#xff0c;受“华为、中兴事件”影响&#xff0c;我国科技尤其是上游核心技术受制于人的现状对我 国经济发展提出了严峻考验。在全球产业从工业经济向数字经济升级的关键时期&#xff0c;中国明确 “数字中国”建设战略&#xff0c; 抢占数字经济产业链制高点。 在…

Python开发工具PyCharm入门指南 - 用户界面主题更改

JetBrains PyCharm是一种Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。此外&#xff0c;该IDE提供了一些高级功能&#xff0c;以用于Django框架下的专业Web开发。 界面主题定义了窗口、对话框、按钮和用户界面的所有可视元素的外观…

vscode开发avalonia

安装 安装.net 8 安装avalonia模板 dotnet new install Avalonia.Templates创建项目 dotnet new avalonia.app -o GetStartedApp安装c# dev kit插件和Avalonia for VSCode Community dotnet run运行 修改代码 MainWindow.axaml <Window xmlns"https://githu…

企业层面经济政策不确定性感知数据(2001-2023年)

1.指标介绍 企业经济政策不确定性感知指的是企业在面对政府经济政策变动时所感受到的风险和不确定性程度&#xff0c;这种感知会影响企业的投资决策、生产计划和市场策略 文章根据上市公司披露的MD&A文本&#xff0c;提取指标衡量企业个体面临的经济政策不确定性。 2.参…