JavaWeb开发——Servlet事件监听器(二)

来源:互联网 发布:免费手机读书软件 编辑:程序博客网 时间:2024/05/16 11:56

监听域对象中属性的变更的监听器

Servlet规范定义了监听ServletContext, HttpSession, HttpServletRequest这三个对象中的属性变更信息事件的监听器。
这三个监听器接口分别是ServletContextAttributeListener,HttpSessionAttributeListener和ServletRequestAttributeListener,这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。

attributeAdded方法

当向被监听对象中增加一个属性时,web容器就调用事件监听器的attributeAdded方法进行响应,这个方法接收一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象。
各个域属性监听器中的完整语法定义为:

  • public void attributeAdded(ServletContextAttributeEvent scae)
  • public void attributeReplaced(HttpSessionBindingEvent hsbe)
  • public void attributeRmoved(ServletRequestAttributeEvent srae)

attributeRemoved方法

当删除被监听对象中的一个属性时,web容器调用事件监听器的attributeRemoved方法进行响应。
各个域属性监听器中的完整语法定义为:

  • public void attributeRemoved(ServletContextAttributeEvent scae)
  • public void attributeRemoved (HttpSessionBindingEvent hsbe)
  • public void attributeRemoved (ServletRequestAttributeEvent srae)

attributeReplaced方法

当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的attributeReplaced方法进行响应。
各个域属性监听器中的完整语法定义为:

  • public void attributeReplaced(ServletContextAttributeEvent scae)
  • public void attributeReplaced (HttpSessionBindingEvent hsbe)
  • public void attributeReplaced (ServletRequestAttributeEvent srae)

ServletContextAttributeListener监听器范例

编写ServletContextAttributeListener监听器监听ServletContext域对象的属性值变化情况,代码如下:

public class MyServletContextAttributeListener implements ServletContextAttributeListener {    @Override    public void attributeAdded(ServletContextAttributeEvent scae) {        // 通过事件对象scae可获知到底往ServletContext域里面存了哪个属性以及其属性值        String name = scae.getName();        Object value = scae.getValue();        System.out.println("向ServletContext域里面存了:" + name + "=" + value);    }    @Override    public void attributeRemoved(ServletContextAttributeEvent scae) {        System.out.println("从ServletContext域里面删除了:" + scae.getName() + "属性");    }    @Override    public void attributeReplaced(ServletContextAttributeEvent scae) {        System.out.println("ServletContext域里面" + scae.getName() + "属性被替换了");    }}

在web.xml文件中注册监听器。

<listener>    <listener-class>cn.itcast.web.listener.MyServletContextAttributeListener</listener-class></listener>

编写index.jsp测试页面

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>ServletContextAttributeListener监听器测试</title></head><body>    <%        // 往application域对象中添加属性        application.setAttribute("name", "李阿昀");        // 替换application域对象中name属性的值        application.setAttribute("name", "liayun");        // 移除application域对象中name属性        application.removeAttribute("name");    %></body></html>

运行结果如下:
这里写图片描述
从运行结果中可以看到,ServletContextListener监听器成功监听到了ServletContext域对象(application)中的属性值的变化情况。

ServletRequestAttributeListener和HttpSessionAttributeListener监听器范例

编写监听器监听HttpSession和HttpServletRequest域对象的属性值变化情况,代码如下:

public class HttpSessionAndServletRequsetAttributeListener        implements HttpSessionAttributeListener, ServletRequestAttributeListener {    @Override    public void attributeAdded(ServletRequestAttributeEvent srae) {        System.out.println("向request中加入东西了!!!");    }    @Override    public void attributeRemoved(ServletRequestAttributeEvent srae) {        System.out.println("从request中删了东西了!!!");    }    @Override    public void attributeReplaced(ServletRequestAttributeEvent srae) {        System.out.println("把request中的属性替换了!!!");    }    @Override    public void attributeAdded(HttpSessionBindingEvent se) {        System.out.println("向session中加入东西了!!!");    }    @Override    public void attributeRemoved(HttpSessionBindingEvent se) {        System.out.println("从session中删了东西了!!!");    }    @Override    public void attributeReplaced(HttpSessionBindingEvent se) {        System.out.println("把session中的属性替换了!!!");    }}

在web.xml文件中注册监听器

<listener>    <listener-class>cn.itcast.web.listener.HttpSessionAndServletRequsetAttributeListener</listener-class></listener>

编写index.jsp测试页面

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>RequestAndSessionAttributeListener监听器测试</title></head><body>    <%              session.setAttribute("name", "aaa");        session.setAttribute("name", "bbb");        session.removeAttribute("name");        request.setAttribute("name", "aaa");        request.setAttribute("name", "bbb");        request.removeAttribute("name");    %></body></html>

运行结果如下:
这里写图片描述
从运行结果中可以看到,HttpSessionAttributeListener监听器和ServletRequestAttributeListener监听器成功监听到了HttpSession域对象和HttpServletRequest域对象的属性值变化情况。
小结:HttpSessionAttributeListener监听器可以用来做显示当前有多少登录用户,每一个用户登录,都往session里面存一个user属性,到时在做开发时,可以写一个监听器来监听session,session里面只要加了user属性,即一个用户登录进来了,到时可以在后台显示当前这个网站到底有多少用户登录进来了。显示出来之后可以踢人,后台管理员发现有人乱说话,就踢掉他。HttpSessionAttributeListener监听器在实际开发中的使用可参见我的笔记监听器(Listener)在开发中的应用(二)——显示登陆用户列表,并实现踢人功能。

感知Session绑定的事件监听器

保存在Session域中的对象可以有多种状态:绑定(session.setAttribute(“bean”,Object))到Session中;从Session域中解除(session.removeAttribute(“bean”))绑定;随Session对象持久化到一个存储设备中(钝化);随Session对象从一个存储设备中恢复(活化)。
Servlet规范中定义了两个特殊的监听器接口”HttpSessionBindingListener和HttpSessionActivationListener”来帮助JavaBean对象了解自己在Session域中的这些状态,实现这两个接口的类不需要在web.xml文件中进行注册

HttpSessionBindingListener接口

实现了HttpSessionBindingListener接口的JavaBean对象可以感知自己被绑定到Session中和从Session中删除的事件

  • 当对象被绑定到HttpSession对象中时,web服务器调用该对象的void valueBound(HttpSessionBindingEvent event)方法。
  • 当对象从HttpSession对象中解除绑定时,web服务器调用该对象的void valueUnbound(HttpSessionBindingEvent event)方法。

范例:

// 注意:现在User既是监听器又是事件源,即监听器监听自己,所以不需要注册到事件源上public class User implements HttpSessionBindingListener {    @Override    public void valueBound(HttpSessionBindingEvent event) {        System.out.println("user对象存到session中了!!!");    }    @Override    public void valueUnbound(HttpSessionBindingEvent event) {        System.out.println("user对象从session解除绑定了!!!");    }}

上述的User这个javabean实现了HttpSessionBindingListener接口,那么这个JavaBean对象可以感知自己被绑定到Session中和从Session中删除的这两个操作,测试代码如下:

<%@page import="cn.itcast.domain.User"%><%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title></title></head><body>    <%          session.setAttribute("user", new User());        session.removeAttribute("user");    %></body></html>

运行结果如下:
这里写图片描述
我们知道当对象被绑定到HttpSession对象中时,web服务器调用该对象的void valueBound(HttpSessionBindingEvent event)方法,所以session类的源代码可能类似于:

class Session {    setAttribute(String key, Object value) {        if(value instanceof HttpSessionBindingListener) {            HttpSessionBindingListener listener = (HttpSessionBindingListener)value;            value.valueBound();        }        set(key, value);    }}

HttpSessionActivationListener接口

实现了HttpSessionActivationListener接口的JavaBean对象可以感知自己被活化(反序列化)钝化(序列化)的事件。

  • 当绑定到HttpSession对象中的javabean对象将要随HttpSession对象被钝化(序列化)之前,web服务器调用该javabean对象的void sessionWillPassivate(HttpSessionEvent event)方法。
    这样javabean对象就可以知道自己将要和HttpSession对象一起被序列化(钝化)到硬盘中。
  • 当绑定到HttpSession对象中的javabean对象将要随HttpSession对象被活化(反序列化)之后,web服务器调用该javabean对象的void sessionDidActive(HttpSessionEvent event)方法。
    这样javabean对象就可以知道自己将要和HttpSession对象一起被反序列化(活化)回到内存中。

范例:

// 注意:一个对象要想到硬盘里面去,必须实现Serializable接口,才能被序列化public class MyBean implements HttpSessionActivationListener, Serializable {    @Override    public void sessionWillPassivate(HttpSessionEvent se) {        System.out.println("javabean随着session到硬盘中去了!!!");    }    @Override    public void sessionDidActivate(HttpSessionEvent se) {        System.out.println("javabean随着session从硬盘回到内存了!!!");    }}

为了观察绑定到HttpSession对象中的javabean对象随HttpSession对象一起被钝化到硬盘上和从硬盘上重新活化回到内存中的的过程,我们需要借助tomcat服务器帮助我们完成HttpSession对象的钝化和活化过程,具体做法如下:
WebRoot\META-INF文件夹下创建一个context.xml文件,如下所示:
这里写图片描述
context.xml文件的内容如下:

<Context>    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">        <Store className="org.apache.catalina.session.FileStore" directory="it315"/>    </Manager></Context>

在context.xml文件中配置了session一分钟没人用了,就将HttpSession对象和javabean对象钝化到本地硬盘的一个it315文件夹中。
jsp页面测试代码如下:

<%@page import="cn.itcast.domain.MyBean"%><%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title></title></head><body>    一访问JSP页面,HttpSession就创建了,创建好的Session的Id是:${pageContext.session.id}    <%          session.setAttribute("bean", new MyBean()); // 当session一分钟没人用,session就和bean一起到硬盘中去了    %></body></html>

访问这个jsp页面,服务器就会马上创建一个HttpSession对象,然后将实现了HttpSessionActivationListener接口的JavaBean对象绑定到session对象中,这个jsp页面在等待1分钟之后没有人再次访问,那么服务器就会自动将这个HttpSession对象钝化(序列化)到硬盘上。
这里写图片描述
我们可以在tomcat服务器的work\Catalina\localhost\day21\it315文件夹下找到序列化到本地存储的session,如下图所示:
这里写图片描述
当再次访问这个jsp页面时,服务器又会自动将已经钝化(序列化)到硬盘上的HttpSession对象重新活化(反序列化)回到内存中。运行结果如下:
这里写图片描述
JavaWeb开发技术中的监听器技术的内容就这么多了,在平时的工作中,监听器技术在JavaWeb项目开发中用得是比较多,因此必须掌握这门技术。

0 0