博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
web之监听器listener
阅读量:3963 次
发布时间:2019-05-24

本文共 11397 字,大约阅读时间需要 37 分钟。

一、概述

1.1 事件监听涉及三个组件

事件监听涉及到三个组件:事件源、事件参数对象、事件监听器。

当事件源上发生某一个动作时,它会调用事件监听器的一个方法,并在调用该方法时把事件参数对象传递进去,

开发人员在监听器中通过事件参数对象,就可以拿到事件源,从而对事件源进行操作。

其原理就是。

1.2 什么是监听器

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

1.3 监听器类型

(1) 声明周期监听器

  1. ServletContext上下文监听器,要实现ServletContextListener接口

    内部方法

    ①初始化:contextInitialized
    ②销毁:contextDestroyed

  2. Session监听器,要实现HttpSessionListener接口

    内部方法

    ①sessionCreated:监听Session对象的创建
    ②sessionDestroyed:监听Session对象的销毁

  3. request监听器,要实现ServletRequestListener接口

    内部方法

    ①requestInitialized:监听request对象的初始化
    ②requestDestroyed:监听request对象的销毁

(2) 属性变化监听器

  1. ServletContext属性变化监听器,实现ServletContextAttributeListener接口

    内部的方法:

    attributeAdded:监听属性的添加
    attributeRemoved:监听属性的移除
    attributeReplaced:监听属性的修改

  2. session属性变化监听器,实现HttpSessionAttributeListener接口,监听HttpSession的内容的变化

    内部方法:

    attributeAdded:监听属性的添加
    attributeRemoved:监听属性的移除
    attributeReplaced:监听属性的修改

  3. request属性变化监听器,继承ServletRequestAttributeListener接口,监听属性内容变化

    内部方法:

    attributeAdded:监听属性的添加
    attributeRemoved:监听属性的移除
    attributeReplaced:监听属性的修改

(3) 感知型监听器

  1. 【对象】从session添加或移除,继承HttpSessionBindingListener接口

    内部方法:

    valueBound:监听对象的绑定
    valueUnbound:监听对象的解除绑定

  2. 对象钝化和活化,继承HttpSessionActivationListener接口

    内部方法:

    sessionWillPassivate:监听Session内部存储对象的钝化-写入硬盘
    sessionDidActivate:监听Session内部存储对象的活化-读取
    对应类需要实现序列化接口Serializable

二、监听器的使用

根据需求,遵从对应的接口,实现相应的方法即可。

2.1 两种配置方式

web.xml中进行配置

com.qf.web.listener.RequestLeftListener

注解

Servlet3.0之后新增的,使用注解【@WebListener】进行监听器的注册

2.2 案例

ServletContextListener接口,主要作用域application

@WebListenerpublic class ApplicationListener implements ServletContextListener {
@Override public void contextInitialized(ServletContextEvent sce) {
System.out.println("初始化程序,提前加载配置文件和jar包"); } @Override public void contextDestroyed(ServletContextEvent sce) {
System.out.println("程序结束的时候释放资源"); }}

HttpSessionListener接口

监听会话的创建和销毁,可以统计在线人数,因为只有浏览器和服务器建立了连接,才会产生session,相当于在线。

HttpSessionListener部分

@WebListenerpublic class OnlineCountListener implements HttpSessionListener {
@Override public void sessionCreated(HttpSessionEvent se) {
//application作用域是整个app程序,不易销毁,可以用来记录session【作用域大的记录作用域小的】 ServletContext application = se.getSession().getServletContext(); synchronized (this) {
Integer count = (Integer) application.getAttribute("count"); if (null == count) {
count = 1; } else {
count++; } application.setAttribute("count", count); //之后count值会发送到前端页面 } } @Override public void sessionDestroyed(HttpSessionEvent se) {
//如果session销毁了,注意不是关闭浏览器,而是超过30分钟没有活跃,或者手动销毁 //销毁了该方法会监听到 ServletContext application = se.getSession().getServletContext(); synchronized (this) {
Integer count = (Integer) application.getAttribute("count"); if (count != null && count > 0) {
count--; } } }}

前端部分

<%@ page contentType="text/html;charset=UTF-8" language="java" %>    当前在线人数    

当前在线人数:${
count}

同样的道理,【ServletRequestListener接口】 可以实现访问人数的统计,因为访问就是单纯的发送请求,不需要建立连接

@WebListenerpublic class VisitCountListener implements ServletRequestListener {
@Override public void requestDestroyed(ServletRequestEvent sre) {
ServletContext application = sre.getServletContext(); synchronized (this) {
Integer count = (Integer) application.getAttribute("count"); if (count != null && count > 0) {
count--; } } } @Override public void requestInitialized(ServletRequestEvent sre) {
ServletContext application = sre.getServletContext(); synchronized (this) {
Integer count = (Integer) application.getAttribute("count"); if (count == null) {
count = 1; } else {
count++; } application.setAttribute("count", count); } }}

三个属性变化监听器

ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener同时遵从,一起实现接口

@WebListenerpublic class AttributeListener implements ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener {
/*上下文的三种属性监听,application*/ @Override public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("Application监听到添加了" + scae.getName() + ":" + scae.getValue()); } @Override public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("Application监听到移除了" + scae.getName() + ":" + scae.getValue()); } @Override public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("Application监听到替换了" + scae.getName() + ":" + scae.getValue()); } /*request的三种属性监听*/ @Override public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println("request监听到添加了" + srae.getName() + ":" + srae.getValue()); } @Override public void attributeRemoved(ServletRequestAttributeEvent srae) {
System.out.println("request监听到移除了" + srae.getName() + ":" + srae.getValue()); } @Override public void attributeReplaced(ServletRequestAttributeEvent srae) {
System.out.println("request监听到替换了" + srae.getName() + ":" + srae.getValue()); } /*session的三种属性监听,application*/ @Override public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("session监听到添加了" + se.getName() + ":" + se.getValue()); } @Override public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("session监听到移除了" + se.getName() + ":" + se.getValue()); } @Override public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("session监听到替换了" + se.getName() + ":" + se.getValue()); }}

servlet部分

@WebServlet(name = "AttrServlet", value = "/attrservlet")public class AttrServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext application = this.getServletContext(); application.setAttribute("appname", "xxx管理系统"); application.setAttribute("appname", "yyy管理系统"); //同一个name设置两次value就是替换 application.removeAttribute("appname"); request.setAttribute("username", "张三"); request.setAttribute("username", "李四"); request.removeAttribute("username"); request.getSession().setAttribute("age", "20"); request.getSession().setAttribute("age", "30"); request.getSession().removeAttribute("age"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response); }}//打印结果Application监听到添加了appname:xxx管理系统Application监听到替换了appname:xxx管理系统Application监听到移除了appname:yyy管理系统request监听到添加了username:张三request监听到替换了username:张三request监听到移除了username:李四session监听到添加了age:20session监听到替换了age:20session监听到移除了age:30

HttpSessionBindingListener接口

主要用于监听【对象】的绑定到session和解绑,需要【domain实体类】遵从【HttpSessionBindingListener接口】,而不是创建监听,注意:不需要注解了

User类,属性是用户名和密码

public class User implements HttpSessionBindingListener {
private String username; private String password; ...构造方法,get,set方法等不展示 //需要实现两个监听方法 @Override public void valueBound(HttpSessionBindingEvent event) {
System.out.println("绑定到session" + event.getName() + ":" + event.getValue() + "sessionId" + event.getSession().getId()); } @Override public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("解绑:" + event.getSession().getId()); }}

servlet类,登录和退出类

/*登录*/@WebServlet(name = "LoginServlet", value = "/loginservlet")public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = new User("damin", "123"); request.getSession().setAttribute("user", user);//对象放进去后,在User类中的绑定监听方法就执行了 System.out.println("用户登录了"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response); }}/*退出*/@WebServlet(name = "LoginOutServlet",value = "/outservlet")public class LoginOutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().removeAttribute("user"); System.out.println("用户退出了"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response); }}//打印结果绑定到sessionuser:User{
username='damin', password='123'}sessionIdB4B93A07C7D58C42A2871902C36916E7用户登录了解绑:B4B93A07C7D58C42A2871902C36916E7用户退出了

对象钝化和活化,继承HttpSessionActivationListener接口【了解】

同样,需要让【domain实体类】遵从并实现这个接口,此外,还必须遵从序列化接口【Serializable】

User类

public class User implements HttpSessionActivationListener, Serializable {
private String username; private String password; ... @Override public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("对象钝化了..."+se.getSession().getId()); } @Override public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("对象活化了..."+se.getSession().getId()); }}

在META-INF(在web下新建)中创建【context.xml】

Session管理器【了解】

基本思路就是将所有session放入一个集合,定时查看是否有问题,超过时间就将其失效。

这里是用来【定制器技术Timer】,参考

public class SessionManagerListener implements ServletContextListener, HttpSessionListener {
private List
sessions; //设定定时器 private Timer timer; @Override public void contextInitialized(ServletContextEvent sce) {
//初始化集合 sessions = Collections.synchronizedList(new LinkedList<>()); timer = new Timer(); //指定任务,每10秒执行一次 timer.schedule(new TimerTask() {
@Override public void run() {
synchronized (sessions) {
//遍历session Iterator
iterator = sessions.iterator(); while (iterator.hasNext()) {
HttpSession session = iterator.next(); //如果最后访问时间和当前时间相差1分钟,则失效 if (System.currentTimeMillis() - session.getLastAccessedTime() > 60000) {
session.invalidate(); System.out.println("删除了session:" + session.getId()); iterator.remove(); } } } } }, 0, 10000); } @Override public void contextDestroyed(ServletContextEvent sce) {
timer.cancel(); //当application结束的时候,也取消定时器 } @Override public void sessionCreated(HttpSessionEvent se) {
System.out.println("会话创建了..." + se.getSession().getId()); //来一个会话就放到集合中 sessions.add(se.getSession()); } @Override public void sessionDestroyed(HttpSessionEvent se) {
}}

javaEE有自己的Session管理机制,基本原理一致

转载地址:http://zpgzi.baihongyu.com/

你可能感兴趣的文章
Mule ESB-Content-Based Routing Tutorial(2)
查看>>
Mule ESB-Content-Based Routing Tutorial(3)
查看>>
年末项目经验总结
查看>>
做事情要放下面子,拿起责任
查看>>
敏捷开发实践(1)-故事工作量估算导致的问题
查看>>
记一次解决jenkins持续构建,自动部署的问题
查看>>
敏捷开发实践(2)-要不要文档?
查看>>
写博意味着什么
查看>>
比较Cint() , int() , fix() ,round()的区别
查看>>
举例说明常用字符串处理函数
查看>>
软件生存期模型
查看>>
制定计划(问题的定义,可行性研究)
查看>>
需求分析
查看>>
软件设计
查看>>
程序编码
查看>>
软件测试
查看>>
软件维护
查看>>
软件项目管理
查看>>
面向过程的分析方法
查看>>
软件设计基础
查看>>