什么是监听器?

类似于前端的事件绑定,java中的监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

监听器怎么分类?

按监听的对象划分

  • a.ServletContext对象监听器
  • b.HttpSession对象监听器
  • c.ServletRequest对象监听器

按监听的事件划分

  • a.对象自身的创建和销毁的监听器
  • b.对象中属性的创建和消除的监听器
  • c.session中的某个对象的状态变化的监听器

一共有哪些监听器?分别处理的是什么事情?

java中一共给我们提供了八个监听器接口,分别用于监听三个域对象,每个监听器都有专门监听的事件

Request 

  1. ServletRequestListener           (处理request对象创建和销毁)
  2. ServleRequestAttributeListener   (处理域对象中的数据添加 替换 删除)

Session

  1. HttpSessionListener              (处理session对象创建和销毁)
  2. HttpSessionAttributeListener      (处理session域对象中的数据添加 修改 删除)
  3. HttpSessionBindingListener       (处理session对象监听器绑定和解绑定接口)
  4. HttpSessionActivationListener     (处理session对象钝化和活化状态接口)

Application 

  1. ServletContextListener            (处理application对象创建和销毁)
  2. 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学习-监听器相关推荐

  1. JavaWeb学习之路——SSM框架之Spring(五)

    前情提要请看JavaWeb学习之路--SSM框架之Spring(四)                                         整合Spring和Mybatis框架 1.在项目的 ...

  2. B站狂神说JavaWeb学习笔记

    JavaWeb学习笔记(根据b站狂神说java编写) 1.基本概念 1.1 前言 静态Web: 提供给所有人看数据不会发生变化! HTML,CSS 动态Web: 有数据交互,登录账号密码,网站访问人数 ...

  3. JavaWeb学习心得总结

    JavaWeb(JSP+Servlet)新手学习心得总结 说明: 由于篇幅的原因,本文只是对于JavaWeb项目的大致数据流程做一个介绍,同时引出一些JavaWeb开发中很基础的知识点,且不会精确到具 ...

  4. 【javaweb学习笔记】servlet-api,filter和Listener

    javaweb学习笔记 1. servlet-api 1.1 servlet初始化 1.2 ServletContext和context-param 2. 什么是业务层 3. IOC 3.1 耦合/依 ...

  5. 【转载】 javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册 - 孤傲苍狼 - 博 http://www.cnblogs.com/xdp-gacl/

    javaweb学习总结(二十二)--基于Servlet+JSP+JavaBean开发模式的用户登录注册 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+Ja ...

  6. JavaWeb学习总结(期末总结)

    JavaWeb学习总结 本学期的JavaWeb课程课时较多,分为理论课和实验课两部分,学习过程比较坎坷,主要原因是相关技术的原理晦涩难懂.在此之前,我对Web相关的技术也有一定的了解.我大一时开始学习 ...

  7. JavaWeb学习--复习

    JavaWeb学习 JavaWeb--Html 1.提交按钮 <button οnclick="alert('你好')">提交</button>,oncli ...

  8. JavaWeb学习笔记(十)--HttpServletRequest

    1. HttpServletRequest简介 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中 2. Ht ...

  9. javaweb学习总结(三十三)——使用JDBC对数据库进行CRUD

    javaweb学习总结(三十三)--使用JDBC对数据库进行CRUD 一.statement对象介绍 Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过 ...

最新文章

  1. mysql100个优化技巧_MySQL 调优/优化的 100 个建议
  2. ajax content download,关于ajax的content-download时间过慢问题的解决方案与思考
  3. 对象及变量的并发访问一
  4. 3.2.5 端到端的学习
  5. mysql optimize 作用_mysql optimize table
  6. “引用作为函数参数”与 “引用作为函数返回值”
  7. openjdk17体验
  8. linux mysql 存储过程乱码,mysql存储过程中 乱码问题解决办法
  9. ICCV2021 | 如何高效视频定位?QMUL北大Adobe强强联手提出弱监督CRM,性能SOTA
  10. 笨办法学 Python · 续 练习 36:简单的计算器
  11. CSS基础——CSS 列表和表单【学习笔记】
  12. STM8L_库函数-模板搭建
  13. 利用ViewPager实现app的启动画面
  14. whistle抓包工具
  15. 在数组后面添加指定元素
  16. 浏览器无法上网,其他软件可以
  17. 看了知乎,直呼牛逼 !
  18. WXSS-WXML-WXS语法
  19. 微信公众号自定义菜单失效,无法设置的解决方法
  20. iphone4s显示问题

热门文章

  1. 博弈论之:薪酬激励机制
  2. Python爬虫实战之一:requests-爬取京东商品详情页面
  3. 从小白到入门,入行量化必须知道的几点
  4. 通过pc算法和随机游走来做根因定位,CloudRanger论文解读
  5. 敏捷开发培训后的感想
  6. 使用R语言对S&P500股票指数进行ARIMA + GARCH交易策略
  7. Twitter实时搜索系统EarlyBird的总结
  8. APP获取气象局所有城市气象预警信息接口
  9. Linux clamav杀毒
  10. 项目外包跟人力外包_您应该外包下一个开源项目吗?