实验六~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、将物…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
