JavaWeb学习-监听器
什么是监听器?
类似于前端的事件绑定,java中的监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。
监听器怎么分类?
按监听的对象划分
- a.ServletContext对象监听器
- b.HttpSession对象监听器
- c.ServletRequest对象监听器
按监听的事件划分
- a.对象自身的创建和销毁的监听器
- b.对象中属性的创建和消除的监听器
- c.session中的某个对象的状态变化的监听器
一共有哪些监听器?分别处理的是什么事情?
java中一共给我们提供了八个监听器接口,分别用于监听三个域对象,每个监听器都有专门监听的事件
Request
- ServletRequestListener (处理request对象创建和销毁)
- ServleRequestAttributeListener (处理域对象中的数据添加 替换 删除)
Session
- HttpSessionListener (处理session对象创建和销毁)
- HttpSessionAttributeListener (处理session域对象中的数据添加 修改 删除)
- HttpSessionBindingListener (处理session对象监听器绑定和解绑定接口)
- HttpSessionActivationListener (处理session对象钝化和活化状态接口)
Application
- ServletContextListener (处理application对象创建和销毁)
- ServletContextAttributeListener (处理application域对象中的数据添加 修改 删除)
监听器如何使用?
两步走使用
- 1定义监听器,根据需求实现对应接口
- 2在web.xml中配置监听器,让监听器工作
接下来我们就挨个认识一下每个监听器及内部方法的作用
一 Requet域监听器
Requet域共有两个监听器接口,分别是
ServletRequestListener
ServleRequestAttributeListener
接下来我们就认识一些每个接口和接口中每个方法的用处
定义监听器类
package com.msb.listener;
import javax.servlet.*;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class MyRequestListener implements ServletRequestListener, ServletRequestAttributeListener {@Overridepublic void requestDestroyed(ServletRequestEvent sre) {// 监听HttpServletRequest对象的销毁 项目中任何一个Request对象的销毁都会触发该方法的执行ServletRequest servletRequest = sre.getServletRequest();System.out.println("request"+servletRequest.hashCode()+"对象销毁了");}@Overridepublic void requestInitialized(ServletRequestEvent sre) {// 监听HttpServletRequest对象的创建并初始化 项目中任何一个Request对象的创建并初始化都会触发该方法的执行ServletRequest servletRequest = sre.getServletRequest();System.out.println("request"+servletRequest.hashCode()+"对象初始化");}@Overridepublic void attributeAdded(ServletRequestAttributeEvent srae) {// 任何一个Request对象中调用 setAttribute方法增加了数据都会触发该方法ServletRequest servletRequest = srae.getServletRequest();String name = srae.getName();Object value = srae.getValue();System.out.println("request"+servletRequest.hashCode()+"对象增加了数据:"+name+"="+value);}@Overridepublic void attributeRemoved(ServletRequestAttributeEvent srae) {// 任何一个Request对象中调用 removeAttribute方法移除了数据都会触发该方法ServletRequest servletRequest = srae.getServletRequest();String name = srae.getName();Object value = srae.getValue();System.out.println("request"+servletRequest.hashCode()+"对象删除了数据:"+name+"="+value);}@Overridepublic void attributeReplaced(ServletRequestAttributeEvent srae) {// 任何一个Request对象中调用 setAttribute方法修改了数据都会触发该方法ServletRequest servletRequest = srae.getServletRequest();String name = srae.getName();Object value = srae.getValue();Object newValue=servletRequest.getAttribute(name);System.out.println("request"+servletRequest.hashCode()+"对象增修改了数据:"+name+"="+value+"设置为:"+newValue);}
}
配置监听器 使用web.xml 或者通过@WebListener注解都可以
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><listener><listener-class>com.msb.listener.MyRequestListener</listener-class></listener>
</web-app>
准备Servlet
@WebServlet(urlPatterns = "/myServlet3.do")
public class MyServlet3 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setAttribute("name", "zhangsan");req.setAttribute("name", "lisi");req.removeAttribute("name");}
}
二 Session域监听器
Session域共有四个监听器接口,分别是
HttpSessionListener
HttpSessionAttributeListener
HttpSessionBindingListener
HttpSessionActivationListener
接下来我们就认识一些每个接口和接口中每个方法的用处
监听器代码
HttpSessionListener
HttpSessionAttributeListener
package com.msb.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
@WebListener
public class MySessionListener implements HttpSessionListener , HttpSessionAttributeListener {@Overridepublic void sessionCreated(HttpSessionEvent se) {System.out.println("任何一个Session对象创建");}@Overridepublic void sessionDestroyed(HttpSessionEvent se) {System.out.println("任何一个Session对象的销毁");}@Overridepublic void attributeAdded(HttpSessionBindingEvent se) {System.out.println("任何一个Session对象中添加了数据");}@Overridepublic void attributeRemoved(HttpSessionBindingEvent se) {System.out.println("任何一个Session对象中移除了数据");}@Overridepublic void attributeReplaced(HttpSessionBindingEvent se) {System.out.println("任何一个Session对象中修改了数据");}
}
HttpSessionBindingListener
package com.msb.listener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
/*
* 可以监听具体的某个session对象的事件的
*
* HttpSessionListener 只要在web.xml中配置或者通过@WebListener注解就可以注册监听所有的Session对象
* HttpSessionBindingListener 必须要通过setAttribute方法和某个session对象绑定之后,监听单独的某个Session对象
* */
public class MySessionBindingListener implements HttpSessionBindingListener {// 绑定方法/*session.setAttribute("mySessionBindingListener",new MySessionBindingListener())*/@Overridepublic void valueBound(HttpSessionBindingEvent event) {System.out.println("监听器和某个session对象绑定了");}// 解除绑定方法/** 当发生如下情况,会触发该方法的运行* 1 session.invalidate(); 让session不可用* 2 session到达最大不活动时间,session对象回收 ;* 3 session.removeAttribute("mySessionBindingListener");手动解除绑定* */@Overridepublic void valueUnbound(HttpSessionBindingEvent event) {}
}
HttpSessionActivationListener
package com.msb.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/public class MySessionActivationListener implements HttpSessionActivationListener {@Overridepublic void sessionWillPassivate(HttpSessionEvent se) {System.out.println("session即将钝化");}@Overridepublic void sessionDidActivate(HttpSessionEvent se) {System.out.println("session活化完毕");}
}
三 Application监听器
Application域共有两个监听器接口,分别是
ServletContextListener
ServletContextAttributeListener
接下来我们就认识一些每个接口和接口中每个方法的用处
监听器代码
package com.msb.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class MyApplicationListener implements ServletContextListener , ServletContextAttributeListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("ServletContext创建并初始化了");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("ServletContext销毁了");}@Overridepublic void attributeAdded(ServletContextAttributeEvent scae) {System.out.println("ServletContext增加了数据");}@Overridepublic void attributeRemoved(ServletContextAttributeEvent scae) {System.out.println("ServletContext删除了数据");}@Overridepublic void attributeReplaced(ServletContextAttributeEvent scae) {System.out.println("ServletContext修改了数据");}
}
案例:
1.需求:记录每次请求中如下的信息并存储进入日志文件请求的来源
- 浏览器所在电脑IP
- 请求的资源 URL
- 请求发生的时间
监听器代码
package com.msb.listener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
@WebListener
public class RequestLogListener implements ServletRequestListener {private SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");@Overridepublic void requestDestroyed(ServletRequestEvent sre) {}@Overridepublic void requestInitialized(ServletRequestEvent sre) {// 获得请求发出的IP// 获得请求的URL// 获得请求产生的时间HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();String remoteHost = request.getRemoteHost();String requestURL = request.getRequestURL().toString();String reqquestDate = simpleDateFormat.format(new Date());// 准备输出流try {PrintWriter pw =new PrintWriter(new FileOutputStream(new File("d:/msb.txt"),true));pw.println(remoteHost+" "+requestURL+" "+reqquestDate );pw.close();} catch (FileNotFoundException e) {e.printStackTrace();}}
}
2.需求:
1当任何一个账户处于登录状态时,在线统计总数+1,离线时-1
2通过session监听器实现计数,但是在线人数要保存在Application域中
准备监听器
package com.msb.listener;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
@WebListener
public class OnLineNumberListener implements HttpSessionListener {@Overridepublic void sessionCreated(HttpSessionEvent se) {// 向application域中 增加一个数字HttpSession session = se.getSession();ServletContext application = session.getServletContext();Object attribute = application.getAttribute("count");if(null == attribute){// 第一次放数据application.setAttribute("count", 1);}else{int count =(int)attribute;application.setAttribute("count", ++count);}}@Overridepublic void sessionDestroyed(HttpSessionEvent se) {// 向application域中 减少一个数字HttpSession session = se.getSession();ServletContext application = session.getServletContext();int count =(int)application.getAttribute("count");application.setAttribute("count", --count);}
}
准备销毁监听的servlet
package com.msb.servlet;
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;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
@WebServlet(urlPatterns = "/logout.do")
public class Logout extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();session.invalidate();}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>$Title%sSourceCode%lt;/title></head><body>当前在线人数为:${applicationScope.count}</body>
</html>
3.项目重启免登录
Session序列化和反序列化
1、序列化与反序列
把对象转化为字节序列的过程称为序列化(保存到硬盘,持久化)
把字节序列转化为对象的过程称为反序列化(存放于内存)
2、序列化的用途
把对象的字节序列永久保存到硬盘上,通常放到一个文件中。
把网络传输的对象通过字节序列化,方便传输本节作业
3、实现步骤
要想实现序列化和反序列化需要手动配置
A、新建文件如图所示:
B、 Context.xml中文件如下
<?xml version="1.0" encoding="UTF-8"?><Context><Manager className="org.apache.catalina.session.PersistentManager"><Store className="org.apache.catalina.session.FileStore" directory="d:/session"/></Manager></Context>
C、注意实体类必须实现serializable 接口
开发过程
1 准备实体类
package com.msb.pojo;
import java.io.Serializable;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class User implements Serializable {private String username;private String pwd;
2.开发登录信息输入页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>$Title%sSourceCode%lt;/title></head><body><form action="loginController.do" method="post">用户名:<input type="text" name="user"> <br/>密码:<input type="password" name="pwd"><br/><input type="submit" value="提交"></form></body>
</html>
3开发登录信息验证Servlet
package com.msb.controller;
import com.msb.listener.MySessionActivationListener;
import com.msb.pojo.User;
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;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
@WebServlet("/loginController.do")
public class LoginController extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("user");String pwd = req.getParameter("pwd");// userUser user =new User(username,pwd);// sessionHttpSession session = req.getSession();session.setAttribute("user", user);}
}
4 开发校验当前是否已经登录的Controller
package com.msb.controller;
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;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
@WebServlet(urlPatterns = "/loginCheckController.do")
public class LoginCheckController extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 判断是否登录HttpSession session = req.getSession();Object user = session.getAttribute("user");Object listener = session.getAttribute("listener");// 获得对应的监听器String message ="";if(null != user){message="您已经登录过";}else{message="您还未登录";}resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=UTF-8");resp.getWriter().println(message);}
}
5测试, 先登录,然后请求loginCheckController.do 校验是否登录过,然后重启项目,再起请求loginCheckController.do 校验是否登录过,发现重启后,仍然是登录过的
6监听钝化和活化
准备监听器
package com.msb.listener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
/*** @Author: Ma HaiYang* @Description: MircoMessage:Mark_7001*/
public class MySessionActivationListener implements HttpSessionActivationListener, Serializable {@Overridepublic void sessionWillPassivate(HttpSessionEvent se) {System.out.println(se.getSession().hashCode()+"即将钝化");}@Overridepublic void sessionDidActivate(HttpSessionEvent se) {System.out.println(se.getSession().hashCode()+"已经活化");}
}
登录时绑定监听器
@WebServlet("/loginController.do")
public class LoginController extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("user");String pwd = req.getParameter("pwd");// userUser user =new User(username,pwd);// sessionHttpSession session = req.getSession();session.setAttribute("user", user);// 绑定监听器session.setAttribute("listener", new MySessionActivationListener());}
}
重启项目 重复测试即可
JavaWeb学习-监听器相关推荐
- JavaWeb学习之路——SSM框架之Spring(五)
前情提要请看JavaWeb学习之路--SSM框架之Spring(四) 整合Spring和Mybatis框架 1.在项目的 ...
- B站狂神说JavaWeb学习笔记
JavaWeb学习笔记(根据b站狂神说java编写) 1.基本概念 1.1 前言 静态Web: 提供给所有人看数据不会发生变化! HTML,CSS 动态Web: 有数据交互,登录账号密码,网站访问人数 ...
- JavaWeb学习心得总结
JavaWeb(JSP+Servlet)新手学习心得总结 说明: 由于篇幅的原因,本文只是对于JavaWeb项目的大致数据流程做一个介绍,同时引出一些JavaWeb开发中很基础的知识点,且不会精确到具 ...
- 【javaweb学习笔记】servlet-api,filter和Listener
javaweb学习笔记 1. servlet-api 1.1 servlet初始化 1.2 ServletContext和context-param 2. 什么是业务层 3. IOC 3.1 耦合/依 ...
- 【转载】 javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册 - 孤傲苍狼 - 博 http://www.cnblogs.com/xdp-gacl/
javaweb学习总结(二十二)--基于Servlet+JSP+JavaBean开发模式的用户登录注册 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+Ja ...
- JavaWeb学习总结(期末总结)
JavaWeb学习总结 本学期的JavaWeb课程课时较多,分为理论课和实验课两部分,学习过程比较坎坷,主要原因是相关技术的原理晦涩难懂.在此之前,我对Web相关的技术也有一定的了解.我大一时开始学习 ...
- JavaWeb学习--复习
JavaWeb学习 JavaWeb--Html 1.提交按钮 <button οnclick="alert('你好')">提交</button>,oncli ...
- JavaWeb学习笔记(十)--HttpServletRequest
1. HttpServletRequest简介 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中 2. Ht ...
- javaweb学习总结(三十三)——使用JDBC对数据库进行CRUD
javaweb学习总结(三十三)--使用JDBC对数据库进行CRUD 一.statement对象介绍 Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过 ...
最新文章
- mysql100个优化技巧_MySQL 调优/优化的 100 个建议
- ajax content download,关于ajax的content-download时间过慢问题的解决方案与思考
- 对象及变量的并发访问一
- 3.2.5 端到端的学习
- mysql optimize 作用_mysql optimize table
- “引用作为函数参数”与 “引用作为函数返回值”
- openjdk17体验
- linux mysql 存储过程乱码,mysql存储过程中 乱码问题解决办法
- ICCV2021 | 如何高效视频定位?QMUL北大Adobe强强联手提出弱监督CRM,性能SOTA
- 笨办法学 Python · 续 练习 36:简单的计算器
- CSS基础——CSS 列表和表单【学习笔记】
- STM8L_库函数-模板搭建
- 利用ViewPager实现app的启动画面
- whistle抓包工具
- 在数组后面添加指定元素
- 浏览器无法上网,其他软件可以
- 看了知乎,直呼牛逼 !
- WXSS-WXML-WXS语法
- 微信公众号自定义菜单失效,无法设置的解决方法
- iphone4s显示问题