实验六~Web事件处理与过滤器
1. 创建一个名为exp06的Web项目,编写、部署、测试一个ServletContext事件监听器。

BookBean代码
package org.example.beans;import java.io.Serializable;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—29* Time: 18:39*/
@SuppressWarnings("serial")
public class BookBean implements Serializable {private String bookId;private String title;private String author;private String publisher;private double price;public String getBookId() {return bookId;}public void setBookId(String bookId) {this.bookId = bookId;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getPublisher() {return publisher;}public void setPublisher(String publisher) {this.publisher = publisher;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}
BookDao代码
package org.example.dao;import org.example.beans.BookBean;import java.sql.*;
import java.util.ArrayList;
import java.util.List;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—29* Time: 18:41*/
public class BookDao {private static Connection c;public BookDao() {try {Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://localhost:3306/web_test";c = DriverManager.getConnection(url, "root", "142516");} catch (Exception e) {e.printStackTrace();}}public List<BookBean> getBooks() {try {String sql = "select * from books";PreparedStatement ps = c.prepareStatement(sql);ResultSet rs = ps.executeQuery();List<BookBean> books = new ArrayList<>();while (rs.next()) {BookBean b = new BookBean();b.setBookId(rs.getString("book_id"));b.setAuthor(rs.getString("author"));b.setTitle(rs.getString("title"));b.setPublisher(rs.getString("publisher"));b.setPrice(rs.getDouble("price"));books.add(b);}return books;} catch (Exception e) {throw new RuntimeException("查询数据库出错", e);}}
}
【步骤1】编写监听器类MyServletContextListener.java,Web应用程序启动时创建一个数据源对象,并将其保存在ServletContext作用域中,Web应用销毁时将其清除;在ServletContext对象上添加属性、删除属性和替换属性时,在Tomcat日志中记录有关信息,包括提示信息、属性名和属性值等。
MyServletContextListener.java
package org.example.config;import javax.servlet.*;
import java.util.Date;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—26* Time: 22:40*/
public class MyServletContextListener implements ServletContextListener, ServletContextAttributeListener {private ServletContext context = null;@Overridepublic void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {context = servletContextAttributeEvent.getServletContext();context.log("添加属性: " + servletContextAttributeEvent.getName()+ ": " + servletContextAttributeEvent.getValue());}@Overridepublic void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {context = servletContextAttributeEvent.getServletContext();context.log("删除属性: " + servletContextAttributeEvent.getName()+ ": " + servletContextAttributeEvent.getValue());}@Overridepublic void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {context = servletContextAttributeEvent.getServletContext();context.log("替换属性: " + servletContextAttributeEvent.getName()+ ": " + servletContextAttributeEvent.getValue());}@Overridepublic void contextInitialized(ServletContextEvent servletContextEvent) {context = servletContextEvent.getServletContext();context.log("应用程序已启动: " + new Date());}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {context = servletContextEvent.getServletContext();context.log("应用程序已销毁: " + new Date());}
}
【步骤2】在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>org.example.config.MyServletContextListener</listener-class></listener>
</web-app>
【步骤3】编写监听器测试页面:contextListenerTest.jsp:使用监听器创建的数据源对象连接是一次实验创建的MySQL数据库test,以表格的形式显示其中books数据表的所有内容。
contextListenerTest.jsp
<%@ page import="java.util.*" %>
<%@ page import="org.example.beans.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="book" class="org.example.dao.BookDao" scope="session" />
<html>
<head><title>contextListenerTest</title>
</head><body><table width="500" height="256" border="1"><tr><th scope="col">bookid</th><th scope="col">title</th><th scope="col">author</th><th scope="col">publisher</th><th scope="col">price</th></tr><%List<BookBean> bookList = book.getBooks();for (BookBean books : bookList) {String book_id = books.getBookId();String title = books.getTitle();String author = books.getAuthor();String publisher = books.getPublisher();double price = books.getPrice();%><tr><td><%=book_id%> </td><td><%=title%></td><td><%=author%></td><td><%=publisher%></td><td><%=price%></td></tr><% } %></table>
</body>
</html>


【步骤5】检查日志文件
打开<CATALINA_HOME>\logs目录中的localhost.yyyy-mm-dd.log日志文件,查看执行事件监听器后写到日志文件中的信息。

2. 编写一个HttpSession事件监听器用来记录当前在线人数。
首先创建一个SessionBean类,用来记录sessionID和注册时间

package org.example.beans;import java.io.Serializable;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—29* Time: 22:17*/
@SuppressWarnings("serial")
public class SessionBean implements Serializable {private String id;private String creationTime;public SessionBean(String id, String creationTime) {this.id = id;this.creationTime = creationTime;}public SessionBean() {}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getCreationTime() {return creationTime;}public void setCreationTime(String creationTime) {this.creationTime = creationTime;}
}
【步骤1】编写MySessionListener监听器处理类,监视Web应用会话创建事件:每创建一个新的会话对象,就将其保存到会话对象的列表数组中,并将用户会话对象列表保存在ServletContext作用域中的sessionList属性中,同时向日志中写入“创建一个新会话”以及该会话的ID。当一个会话对象被删除时,从用户会话对象列表中删除该会话对象并保存,同时向日志中写入“删除一个会话”以及该会话的ID。
package org.example.config;import org.example.beans.SessionBean;import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—29* Time: 21:59*/
public class MySessionListener implements HttpSessionListener {@Overridepublic void sessionCreated(HttpSessionEvent httpSessionEvent) {ServletContext application = httpSessionEvent.getSession().getServletContext();List<SessionBean> sessionList = (List<SessionBean>)application.getAttribute("sessionList");if (sessionList == null) {sessionList = new ArrayList<>();application.setAttribute("sessionList", sessionList);}long time = httpSessionEvent.getSession().getCreationTime();Date date = new Date(time);SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String creationTime = sd.format(date);SessionBean sessionBean = new SessionBean(httpSessionEvent.getSession().getId(),creationTime);sessionList.add(sessionBean);application.log("创建一个新会话,其id为: " + httpSessionEvent.getSession().getId());}@Overridepublic void sessionDestroyed(HttpSessionEvent httpSessionEvent) {ServletContext application = httpSessionEvent.getSession().getServletContext();List<SessionBean> sessionList = (List<SessionBean>)application.getAttribute("sessionList");String sessionId = httpSessionEvent.getSession().getId();for(SessionBean session : sessionList) {if (session.getId().equals(sessionId)) {sessionList.remove(session);}}application.log("删除一个新会话,其id为: " + sessionId);application.setAttribute("sessionList", sessionList);}
}
【步骤2】在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>org.example.config.MyServletContextListener</listener-class></listener><listener><listener-class>org.example.config.MySessionListener</listener-class></listener>
</web-app>
【步骤3】编写一个测试该监听器的页面sessionDisplay.jsp,显示当前应用所有在线的会话对象的id及创建时间。多打开几个浏览器窗口,模拟多用户访问,查看多用户会话统计出的结果。
<%@ page import="java.util.*" %>
<%@ page import="org.example.beans.*" %>
<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head><title>sessionDisplay</title>
<style>td{text-align: center;}
</style>
</head>
<body><table width="500" height="256" border="1"><tr><th scope="col">会话id</th><th scope="col">创建时间</th></tr><%ServletContext context = getServletConfig().getServletContext();List<SessionBean> sessionList = (List<SessionBean>) context.getAttribute("sessionList");for (SessionBean s : sessionList) {String id = s.getId();String creationTime = s.getCreationTime();%><tr><td><%=id%> </td><td><%=creationTime%></td></tr><% } %></table>
</body>
</html>

3. 编写一个ServletRequestListener监听器,记录某个页面自应用程序启动以来被访问的次数。
【步骤1】编写监听器接口MyRequestListener,在对指定页面onlineCount.jsp发送请求时进行该页面访问次数计数器累加,并将计数器变量保存到应用作用域的属性中。
package org.example.config;import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—30* Time: 0:04*/
public class MyRequestListener implements ServletRequestListener {private int count = 0;@Overridepublic void requestDestroyed(ServletRequestEvent servletRequestEvent) {}@Overridepublic void requestInitialized(ServletRequestEvent servletRequestEvent) {HttpServletRequest request1 = (HttpServletRequest) servletRequestEvent.getServletRequest();if(request1.getRequestURI().equals("/exp06/onlineCount.jsp")){count++;servletRequestEvent.getServletContext().setAttribute("count",new Integer(count));}}
}
【步骤2】在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>org.example.config.MyServletContextListener</listener-class></listener><listener><listener-class>org.example.config.MySessionListener</listener-class></listener><listener><listener-class>org.example.config.MyRequestListener</listener-class></listener>
</web-app>
【步骤3】编写一个JSP页面onlineCount.jsp。
<%@ page contentType="text/html;charset=utf-8" language="java" %>
<html>
<head><title>Listener test</title>
</head>
<body>
欢迎您,您的IP地址是<%= request.getRemoteAddr() %>
<p>自应用程序启动以来,该页面被访问了
<font color="blue" ><%=application.getAttribute("count")%>
</font>次<br>
</body>
</html>
【步骤4】启动多个浏览器窗口访问该jsp页面,展示并分析程序的运行结果。

相关文章:
实验六~Web事件处理与过滤器
1. 创建一个名为exp06的Web项目,编写、部署、测试一个ServletContext事件监听器。 BookBean代码 package org.example.beans;import java.io.Serializable;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—29* Time: 18:39*/ Su…...
刷题4.28
1、 开闭原则软件实体(模块,类,方法等)应该对扩展开放,对修改关闭,即在设计一个软件系统模块(类,方法)的时候,应该可以在不修改原有的模块(修改关…...
做了一年csgo搬砖项目,还清所有债务:会赚钱的人都在做这件事 !
前段時间,在网上看到一句话:有什么事情,比窮更可怕? 有人回答说:“又忙又窮。” 很扎心,却是绝大多数人的真实写照。 每天拼死拼活的996,你有算过你的時间值多少钱? 我们来算一笔…...
线性回归模型(7大模型)
线性回归模型(7大模型) 线性回归是人工智能领域中最常用的统计学方法之一。在许多不同的应用领域中,线性回归都是非常有用的,例如金融、医疗、社交网络、推荐系统等等。 在机器学习中,线性回归是最基本的模型之一&am…...
VP记录:Codeforces Round 868 (Div. 2) A~D
传送门:CF A题:A-characteristic 构造一个只有 1 , − 1 1,-1 1,−1的数组,满足乘积为 1 1 1的数对的个数为 k k k. 发现 n n n的范围很小,考虑直接暴力枚举数组中 1 1 1的个数,记为 i i i,那么对于1的所有数对来说,我们有 i ∗ ( i − 1 ) / 2 i*(i-1)/2 i∗(i−1)/2个,然后…...
【VQ-VAE-2论文精读】Generating Diverse High-Fidelity Images with VQ-VAE-2
【VQ-VAE-2论文精读】Generating Diverse High-Fidelity Images with VQ-VAE-2 0、前言Abstract1 Introduction2 Background2.1 Vector Quantized Variational AutoEncoder3 Method3.1 Stage 1: Learning Hierarchical Latent Codes3.2 Stage 2: Learning Priors over Latent C…...
并发编程基石:管程
大家好,我是易安! 如果有人问我学习并发并发编程,最核心的技术点是什么,我一定会告诉他,管程技术。Java语言在1.5之前,提供的唯一的并发原语就是管程,而且1.5之后提供的SDK并发包,也…...
电路中噪声来源
电路包括不同的部件和芯片,所有都有可能成为噪声的来源。例如,电阻会带来热噪声,这个噪声为宽频噪声,几乎涵盖所有频率范围;运算放大器其芯片内部会产生噪声;而 ADC产生的量化噪声相较于其他器件࿰…...
JAVASE的全面总结
(未完待续) 五、子类与继承 5.1 子类与父类 继承是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并…...
关于repeater录制的流量子调用的identity中带有~S的情况
前段时间同事问我,我们录制的流量中,尤其是dubbo的子调用显示经常他的末尾会带上一个小尾巴这个是什么意思呢,其实之前我没有太在意这个事情,只是同事这么疑问了,确实激起了好奇心,所以就差了下 到底是什么…...
Java面试题队列
Java中的队列都有哪些,有什么区别 1. ArrayDeque, (数组双端队列) 2. PriorityQueue, (优先级队列) 3. ConcurrentLinkedQueue, (基于链表的并发队列) 4. DelayQueue, (延期…...
大型Saas系统的权限体系设计(二)
X0 上期回顾 上文《大型Saas系统的权限体系设计(一)》提到2B的Saas系统的多层次权限体系设计的难题,即平台、平台的客户、客户的客户,乃至客户的客户的客户如何授权,这个可以通过“权限-角色-岗位”三级结构来实现。 但这个只是功能权限&am…...
HTML(四) -- 多媒体设计
目录 1. 视频标签 2. 音频标签 3. 资源标签(定义媒介资源 ) 1. 视频标签 属性值描述autoplayautoplay如果出现该属性,则视频在就绪后马上播放。controlscontrols表示添加标准的视频控制界面,包括播放、暂停、快进、音量等…...
设置苹果电脑vsode在新窗口中打开文件
0、前言 最近切换到mac电脑工作,又得重新安装一些工具软件并设置。虽然这些设置并表示啥复杂的设置,但是久了不设置还是会忘记。于是记录之,也希望给能帮助到需要的人。 我们使用vscode阅读或者编辑文件时,有时候希望同时打开多…...
第二章创建模式—单例设计模式
文章目录 单例模式的结构如何控制只有一个对象呢怎么设计这个类的内部对象外部怎么访问 单例模式的主要有以下角色 单例模式的实现饿汉式 1:静态变量饿汉式 2:静态代码块懒汉式 1:线程不安全懒汉式 2:线程安全—方法级上锁懒汉式 …...
数据结构学习记录——堆的插入(堆的结构类型定义、最大堆的创建、堆的插入:堆的插入的三种情况、哨兵元素)
目录 堆的结构类型定义 最大堆的创建 堆的插入 堆的插入的三种情况 代码实现 哨兵元素 堆的结构类型定义 #define ElementType int typedef struct HNode* Heap; /* 堆的类型定义 */ struct HNode {ElementType* Data; /* 存储元素的数组 */int Size; /* 堆中…...
netperf测试
netperf测试 目录 批量网络流量性能测试 TCP_STREAM测试UDP_STREAM 测试请求/应答网络流量测试 TCP_RR TCP_CRR Netperf 是一个网络性能测试工具,它可以测试网络协议栈的性能,例如TCP和UDP协议。Netperf可以测量网络吞吐量、延迟和CPU利用率等指标。…...
ORACLE常用语句
1.修改用户密码 alter user 用户名 identified by 新密码; 2.表空间扩容 1.增加数据文件 alter tablespace AA add datafile ‘DATA’ size 20G autoextend off; 2.修改数据文件大小 ALTER DATABASE DATAFILE ‘E:\ORACLE\PRODUCT\10.2.0\ORADATA\aa\aa.DBF’ RESIZE 400M;…...
[论文笔记]C^3F,MCNN:图片人群计数模型
(万能代码)CommissarMa/Crowd_counting_from_scratch 代码:https://github.com/CommissarMa/Crowd_counting_from_scratch (万能代码)C^3 Framework开源人群计数框架 科普中文博文:https://zhuanlan.zhihu.com/p/65650998 框架网址:https…...
HCIP-7.2VLAN间通信单臂、多臂、三层交换方式学习
VLAN间通信单臂、多臂、三层交换方式学习 1、单臂路由2、多臂路由3、三层交换机的SVI接口实现VLAN间通讯3.1、VLANIF虚拟接口3.2、VLAN间路由3.2.1、单台三层路由VLAN间通信,在一台三层交换机内部VLAN之间直连。3.2.2、两台三层交换机的之间的VLAN通信。3.2.3、将物…...
深入ARM指令集:除了SWI和BKPT,CLZ指令如何优化你的算法性能?
深入ARM指令集:CLZ指令如何成为算法优化的秘密武器? 在嵌入式开发的世界里,性能优化往往意味着在硬件限制与软件效率之间寻找完美平衡。当大多数开发者还在为循环展开和缓存优化绞尽脑汁时,ARM架构中那些鲜为人知的特殊指令——比…...
拆解工厂物料管理系统,看工厂物料管理系统如何解决账实不符
在工厂的日常运营中,物料管理是最基础也最容易出问题的环节。你可能会遇到这样的情况:仓库账面上显示还有100个零件,生产急用时却翻遍货架找不到;采购按计划下单,结果库存早已积压;月底盘点,账实…...
2026最权威的六大降AI率工具推荐榜单
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 去降低那AI生成文本被检测出来的概率,其核心要点在于去模仿人类写作所具备的那种…...
多摩川编码器通信避坑指南:STM32 RS485接线、供电不稳、通信失败的排查与修复
多摩川编码器与STM32的RS485通信实战:从硬件设计到故障排查的完整指南 当你在深夜的实验室里盯着示波器上杂乱的波形,反复检查代码却依然无法与多摩川编码器建立通信时,那种挫败感每个嵌入式工程师都深有体会。RS485通信看似简单,…...
STM32/GD32烧录失败别慌:手把手教你用BOOT0引脚和Keil的‘under Reset’模式救砖
STM32/GD32烧录失败自救指南:从硬件短接到调试模式全解析 第一次遇到芯片无法烧录的情况时,那种手足无措的感觉我至今记忆犹新。开发板静静地躺在桌面上,Keil里不断弹出的错误提示仿佛在嘲笑我的无能。但别担心,这几乎是每个嵌入式…...
ORAN前传延迟实战:手把手教你配置O-DU与O-RU的时间窗(含eCPRI测量避坑)
ORAN前传延迟实战:从参数配置到eCPRI测量的全流程指南 在5G O-RAN架构中,前传延迟管理是确保系统性能的关键环节。本文将深入探讨如何基于O-RU的延迟参数报告和网络测量结果,精确计算O-DU的发送窗和接收窗,并通过eCPRI单向延迟测量…...
《QClaw白名单精细化配置全指南,从入门到精通》
深夜的台灯把桌面切成明暗两半,指尖悬在鼠标上迟迟不敢落下,屏幕里是攒了半个月的项目初稿和客户签字的保密协议扫描件。窗外的车流声渐渐稀疏,整个房间只剩下键盘敲击的余响和自己的心跳声。之前有过一次糟糕的经历,用某款热门云…...
四轴无人机飞控核心:深入理解MPU6050数据融合与STM32的PID控制环路
四轴无人机飞控核心:深入理解MPU6050数据融合与STM32的PID控制环路 当四轴无人机在风中稳稳悬停时,很少有人会思考这背后精妙的控制艺术。就像杂技演员走钢丝时不断调整身体姿态一样,无人机也在以每秒数百次的速度进行着微观调整。这种看似简…...
如何永久保存微信聊天记录:WeChatMsg让你的数字记忆永不丢失
如何永久保存微信聊天记录:WeChatMsg让你的数字记忆永不丢失 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we…...
别再死记硬背编译原理了!用Java手搓一个DFA字符串识别器(附完整源码)
用Java实现DFA字符串识别器:从理论到实战的编译原理实践 编译原理作为计算机科学的核心课程之一,常常让学习者感到抽象难懂。特别是有限自动机(DFA)这类概念,如果仅停留在理论层面,很难真正掌握其精髓。本文…...
