收获总结:
①什么是监听器
专门用于对其他对象身上发生的事件或者状态的改变进行监听和处理的对象,当被监听的对象发生改变时立即采取相应的行动。
Servlet监听器:这是Servlet规范中定义的一种特殊的类,他用于监听web应用程序的ServletContext,HttpSession,ServletRequest等域对象的创建和销毁,属性发生修改的事件。
②监听器的类型有哪些呢?
按照Servlet监听的事件类型主要分为三种:
(1)监听域对象的创建和销毁的监听器
监听域对象创建和销毁的监听器接口有三个分别是:ServletContextListener,HttpSessionListener,ServletRequestListener。
如何创建监听器呢?
其实就是实现对应域对象的监听器的接口的java类。
java代码如下:
package com.yd.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
//监听域对象自身的创建和销毁
public class CreateDestroyListener implements ServletContextListener,HttpSessionListener,ServletRequestListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("Context is destroyed");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("Context is created");
}
@Override
public void requestDestroyed(ServletRequestEvent arg0) {
System.out.println("Request is destroyed");
}
@Override
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("Request is created");
}
@Override
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("Session is created");
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("Session is destroyed");
}
}
当我们创建完监听器之后需要在web.xml中配置,在服务器加载web应用的时候就会将这些监听器创建并且存储。实现对域对象的监听。配置如下:
从以上代码很容易看的出来监听器的包含两个方法一个是初始化方法一个是销毁方法,虽然方法名字不同但是都是监听域对象的创建和销毁时之行的。而且每个方法都有一个事件对象参数。接下来就以ServletContextListener的两个方法为例说明一下:contextInitialized(ServletContextEvent arg0)方法当ServletContext被创建时执行的,contextDestroyed(ServletContextEvent arg0)方法是在ServletContext销毁的时候被执行的。这两个方法都有一个ServletContextEvent事件参数,通过这个参数可以获得当前域对象。其他两个域对象的监听器也是大体如此。
(2)监听域对象属性修改的监听器
监听域对象属性修改的监听器也有三个分别是:ServletContextAttributeListener,ServletRequestAttributeListener,HttpSessionAttributeListener。
域对象属性监听器创建的方式和域对象监听器的创建一样,java代码如下:
package com.yd.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class AttributeModifiedListener implements ServletContextAttributeListener,ServletRequestAttributeListener,HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent arg0) {
System.out.println("Session attribute add");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent arg0) {
System.out.println("Session attribute remove");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent arg0) {
System.out.println("Session attribute replace");
}
@Override
public void attributeAdded(ServletRequestAttributeEvent arg0) {
System.out.println("Request attribute add");
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent arg0) {
System.out.println("Request attribute remove");
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent arg0) {
System.out.println("Request attribute replace");
}
@Override
public void attributeAdded(ServletContextAttributeEvent arg0) {
System.out.println("Context attribute add");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent arg0) {
System.out.println("Context attribute remove");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent arg0) {
System.out.println("Context attribute replace");
}
}
同样我们创建完域对象属性监听器之后也需要在web.xml文件中配置,当服务器启动时才会即使创建该监听器并且对域对象属性的修改进行监听,配置如下图:
同样这三个域对象属性监听器的用法也是大致相同这里主要以ServletRequestAttributeListener为例。ServletRequestAttributeListener监听器有三个方法,attributeAdded(ServletRequestAttributeEvent arg0),
attributeRemoved(ServletRequestAttributeEvent arg0),attributeReplaced(ServletRequestAttributeEvent arg0)三个方法,是用来监听ServletRequest对象添加,移除和替换属性值时执行的方法。他们都有ServletRequestAttributeEvent参数,此对象有getName()和getValue()方法是用来获得域对象设置的属性的名字和值。其它两个域对象属性监听器也是大致相同就不重复说了。
(3)监听绑定到HttpSession域对象中的某个对象的状态的事件监听器
监听绑定到HttpSession域对象中的某个对象的状态的事件监听器有两种一个是HttpSessionBindingListener,一个是HttpSessionActivationListener。这两个监听器都用来监听某一类对象的,所以在声明类的
时候实现该接口就行,也就是说我们在创建该类对象时就自带监听器,所以这两个监听器不需要在web.xml中配置。
实现HttpSessionBindingListener监听器是用来监听对象绑定到HttpSession中监听器,java实现代码如下:
package com.yd.bean;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.w3c.dom.events.EventException;
/*
* 实现该监听器的java类
* 监听该类对象被存储到session域对象或者被移除session域对象事件
*/
public class Student implements HttpSessionBindingListener {
private String name;
private Integer age;
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("it is binded in session"+" name:"+event.getName()+" value:"+event.getValue());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("it is unbinded in session"+" name:"+event.getName()+" value:"+event.getValue());
}
}
实现该监听器需要实现两个方法,valueBound(HttpSessionBindingEvent event) 方法,当该类的对象绑定到HttpSession中时执行该方法。valueUnbound(HttpSessionBindingEvent event) 方法,当该类对象被HttpSession移除时执行该方法。这两个方法中有一个HttpSessionBindingEvent参数,此对象有两个getName()方法,getValue()方法和getSession()方法来获得对象存入HttpSession中的名字和对象值,以及获得HttpSession对象本身。
HttpSessionActivationListener实现该监听的类对象可以随着session活化(从磁盘中读取出来存储到内存中)和钝化(从内存中读取出来写到磁盘中)。因为这里需要将类对象写到磁盘和从磁盘中读取出来所以该类还必须要实现Serializable序列化接口。那么什么情况下session会被写到磁盘和从磁盘中读取出来呢?
关于session会话技术,当浏览器没有关闭的时候服务器突然关闭了,如果此时session的生命周期还没有结束,那么session将会被服务器写入到磁盘中去,当服务器启动时会再次从磁盘中读取该session写到内存中。这样浏览器发送请求时,获得的还是之前独享的那个session。所以如果希望我们存储在session中的属性也会随之写入磁盘和读出磁盘那么就是让该属性实现序列化接口和HttpSessionActivationListener。这样属性对象就会随session被钝化和活化。
java实现代码如下:
package com.yd.bean;
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
public class Customer implements HttpSessionActivationListener,Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Customer [name=" + name + "]";
}
public Customer(String name) {
super();
this.name = name;
}
public Customer() {
super();
}
//对象随着session读出磁盘 活化
@Override
public void sessionDidActivate(HttpSessionEvent arg0){
System.out.println("it is activating");
}
//对象随着session写入到磁盘 钝化
@Override
public void sessionWillPassivate(HttpSessionEvent arg0){
System.out.println("it is passivating");
}
}
实现该监听器接口就要实现两个方法,sessionDidActivate(HttpSessionEvent arg0)方法是当对象随着session从磁盘中读取出来时执行的,sessionWillPassivate(HttpSessionEvent arg0)方法是在对象随着session被写入到磁盘中时执行的。他们都有HttpSessionEvent这个参数对象,通过该对象可以通过getSession()方法获得session对象。并执行一些操作。