今天我们来讲一讲监听器。
1..Servlet监听器
① 监听器就是专门用于对某个对象身上发生的事件或者状态改变进行监听和相应处理的对象,当被监听的对象发生改变时立即采取相应行动。
②Servlet监听器,Servlet规范中定义的一些特殊的类,用于监听三个域对象ServletRequest/HttpSession/ServletContext的创建和销毁、ServletRequest/HttpSession/ServletContext属性的改变(添加,修改,移除)、对Javabean对象在HttpSession中的状态改变
③ Servlet监听器的分类:
a: 用于监听ServletRequest/ServletContext/HttpSession这三个域对象在Servlet容器中的创建和销毁的时机
b:用于监听ServletRequest/ServletContext/HttpSession这三个域对象中的属性对象的状态改变(添加属性对象,修改属性对象,删除属性对象)
c::用于监听绑定到HttpSession中的Javabean对象的状态改变的监听器
2. 三个域对象的创建和销毁监听器
① 继承这三个域对象的监听器接口:ServletRequestListener/HttpSessionListener/ServletContextListener(这个监听器最常用)
② 实现当中的两个方法:context/request/sessionInitialized() 和 context/request/sessionDestroyed(ServletContextEvent sce) 其中这个参数ServletContextEvent可以获取ServletContext对象
需要注意的是:这两个方法中initail方法是当被监听的域对象创建之后立即被触发,而destroy方法是当被监听的域对象销毁后被触发。
③ 需要在web.xml文件中将这个监听器类注册一下,才可以使用
需要注意的是:ServletContextListener是最常用的一个监听器,我们常常在这个监听中进行一些整个项目的初始化操作,如:创建数据库连接池,创建IOC容器,获取当前WEB应用的初始化参数等等。
3.三个域对象的属性改变的监听器(较少使用)
① ServletContextAttributeListener/HttpSessionAttributeListener/ServletRequestAttributeListener
② 继承者三个接口的监听器类,需要重写三个抽象方法,attributeAdded(ServletRequestAttributeEvnt srae) attributeRemove() attributeReplaced() ,这三个方法分别在被监听对象的属性发生添加,删除,修改时被触发执行,其中的参数可以用于获取被监听的域对象和域对象中添加,修改,删除的对象的属性和属性值。需要注意的是,获取修改的属性值是被修改的属性值,而不是修改之后的属性值。
4. 监听HttpSession中Javabean对象的状态的监听器(少用,了解)
① HttpSession中Javabean的状态:Javabean对象被绑定包HttpSession中,Javabean对象从HttpSession对象中移除,Javabean对象随着HttpSession对象持久化到本地磁盘,Javabean对象随着HttpSession对象从一个磁盘中移除
② Servlet规范定义了两个特殊性的不必在web.xml中进行注册的监听器接口,帮助Javabean对象了解自己在Session域中的这些状态:HttpSessionBindListener/HttpSessionActionalListener
③ HttpSessionBindListener:这个接口是让Javabean对象来了解自己保存和移除在HttpSession域对象中的情况,当对应的Javabean对象保存在HttpSession中时,触发Javabean类重写的valueBind()方法,当对应的Javabean对象从HttpSession中移除时,触发Javabean类重写的valueUnbind()方法,其中的参数形如HttpSessionBindEvent可以用来获取HttpSession域对象和其Javabean对象的属性和属性值
④ HttpSessionActiviation接口:实现这个接口的Javabean类的对象可以了解其对象是否随着HttpSession对象持久化到了磁盘中以及是否随着HttpSession对象从磁盘中移除。当Javabean对象随着HttpSession对象持久化到磁盘中时,其重写的HttpSessionActiviation接口的sessionWillPassivate()方法就会被触发;当Javabean对象随着HttpSession对象从磁盘中移除时,Javabean重写的sessionDidActive()方法就会被触发,前提是这个Javabean类必须实现序列化接口和这个监听器接口。
需要注意的是:我们在将一个Java对象序列化到磁盘上前,获取一个哈希值;然后将这个保存到磁盘上的Java对象反序列化到JVM内存中,再计算这个Java对象的哈希值,发现前后两个哈希值发生了变化,这是为什么呢?这时因为我们采用散装存取的方式来对这个Java对象序列化和反序列化。当我们将一个Java对象从内存中存入到磁盘中时,需要通过序列化将其打散了放到磁盘中;而当我们将这个Java对象从磁盘上读取到内存中时,也是将这些打散了的值拼装在一起,所以期间发生了些许改变。那么如何确定再次取出的Java对象是之前存入的Java对象呢?我们可以在时间维度上对其进行精准的定位:即我们为每一个Java对象都创建一个代表当前时间的属性time,通过这个time确定Java对象的唯一性。
5.通过域对象创建和销毁监听器来了解三个域对象的创建和销毁的时机
① reqeust
这个对象代表了一个请求,当发起一个请求时Servlet容器才会创建一个request对象,当目标资源返回响应时这个request请求会被销毁。
可以看到在请求转发中:Servlet容器创建和销毁了一次request对象,可知请求的转发从始至终都是同一个请求。
在请求的重定向中:Servlet容器创建和销毁了两次request对象,可知请求的重定向从始至终是两个不同的请求。
② session(重要)
session是一个会话,创建时机是当我们第一次访问一个web应用jsp页面或者servlet,且这个jsp或者servlet还需创建session对象时,那么servlet容器会创建一个隐含的session对象。
session对象在servlet容器中销毁的时机:
a:通过session.setMaxInactiveInternai(秒)设定的session对象的有效时间过期。session默认的过期时间是30分钟。
b:手动的调用session.invalidate()方法,是当前jsp或者servlet代表的session创建之后立即被销毁。
c:从WEB服务器上卸载当前WEB应用时,不一定会销毁session对象:因为若对当前session对象调用了setMaxInactiveInternal方法设定了session的持久化时间,那么当卸载web应用的时候,session对象会被保存到一个持久化文件中,若重写加载web应用,则这个持久化文件会被重新加载到WEB应用中。
d:关闭浏览器也不一定意味着session对象的销毁:只要第二次打开浏览器时使用url编程将JSESSIONID附着于URL之后传给web服务器就可以。
③ application
这个对象代表的是当前web应用,他在当前到的web应用被加载时进行创建,在当前web应用被卸载时进行销毁。