JavaWeb三大组件之监听器(Listener)

监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。

上述概念设计到3个名词概念:

  • 1.事件源:即谁产生的事件
  • 2.事件对象:即产生了什么事件
  • 3.监听器:监听事件源的动作

由于事件源可以产生多个动作(即产生多个事件),而监听器中的每一个方法监听一个动作,故每个监听器中都有很多方法。

1.JavaWeb中的监听器

1.1概念

JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext、HttpSession和 ServletRequest这三大域对象的创建、销毁事件以及监听这些域对象中的属性发生修改的事件。

1.2JavaWeb中监听器的分类

在Servlet规范中定义了多种类型的监听器(一共8个监听器),它们用于监听的事件源分别为ServletContext,HttpSession和ServletRequest这三个域对象。Servlet规范针对这三个对象上的操作,又把多种类型的监听器划分为三种类型:

  • 1.域对象的生命周期监听:监听域对象自身的创建和销毁。这个监听器需要实现相应的监听器接口:ServletContextListener、HttpSessionListener、ServletRequestListener。
  • 2.域对象的属性监听:监听域对象中属性的增加和删除。这个监听器需要实现的监听器接口为:ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener
  • 3.感知监听(都与HttpSession域对象有关):监听绑定到HttpSession域中的某个JavaBean对象的状态的监听器。这个监听器需要实现的监听器接口:HttpSessionBindingListener、HttpSessionActiveationListener.

1.3第一类:域对象的生命周期监听

事件源为:三大域
事件对象为:创建与销毁
监听器为:实现了ServletContextListener、HttpSessionListener、ServletRequestListener这三个接口的监听器

1.3.1ServletContext的生命周期监听

1
2
3
4
5
6
7
8
9
10
11
12
public class AListener implements ServletContextListener{

public void contextInitialized(ServletContextEvent sce)
{

//在项目启动时调用
}

public void contextDestroyed(ServletContextEvent sce)
{

//在项目关闭时调用
}
}

在web.xml文件中对该监听器进行配置:

1.3.2HttpSession的生命周期监听

代码同上述基本一致:

1
2
3
4
5
6
7
8
9
10
11
12
public class AListener implements HttpSessionListener{

public void sessionCreated(HttpSessionEvent sce)
{

//在会话产生时调用
}

public void sessionDestroyed(HttpSessionEvent sce)
{

//在会话关闭时调用
}
}

同样需要在web.xml文件中进行配置:

1.3.3ServletRequest的生命周期

代码同上述基本一致:

1
2
3
4
5
6
7
8
9
10
11
12
public class AListener implements ServletRequestListener{

public void rquestInitialized(ServletRequestEvent sce)
{

//在请求产生时调用
}

public void requestDestroyed(ServletRequestEvent sce)
{

//在请求关闭时调用
}
}

同样需要在web.xml文件中进行配置:

1.3.4对各个监听器接口的方法中出现的类介绍

ServletContextEvent类:类中有一个方法getServletContext(),该方法返回ServletContext对象。

HttpSessionEvent类:类中有一个方法getSession(),该方法返回一个HttpSession对象。

ServletRequestEvent类:类中有两个方法,getServletContext()用于返回一个ServletContext对象,getServletRequest()用于返回一个ServletRequest对象。

1.4第二类:域对象的属性监听

事件源:三大域
事件对象:属性的增加与删除
监听器:实现了ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener接口的监听器

1.4.1ServletContext的属性监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AListener implements ServletContextAttributeListener{

public void attributeAdded(ServletcontextAttribute scab){
//给ServletContext对象添加属性时调用
}

public void attributeRemoved(ServletContextAttributeEvent scab){
//给ServletContext对象删除属性时调用
}

public void attributeReplaced(ServletContextAttributeEvent scab){
//给ServletContext对象替换属性值时调用
}
}

同样需要在web.xml文件中对AListener进行配置。

1.4.2HttpSession的属性监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AListener implements HttpSessionAttributeListener{

public void attributeAdded(HttpSessionAttribute scab){
//给HttpSession对象添加属性时调用
}

public void attributeRemoved(HttpSessionAttributeEvent scab){
//给HttpSession对象删除属性时调用
}

public void attributeReplaced(HttpSessionAttributeEvent scab){
//给HttpSession对象替换属性值时调用
}
}

同样需要在web.xml中对AListener进行配置。

1.4.3ServletRequest的属性监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AListener implements ServletRequestAttributeListener{

public void attributeAdded(ServletRequestAttribute scab){
//给ServletRequest对象添加属性时调用
}

public void attributeRemoved(ServletRequestAttributeEvent scab){
//给ServletRequest对象删除属性时调用
}

public void attributeReplaced(ServletRequestAttributeEvent scab){
//给ServletRequest对象替换属性值时调用
}
}

同样需要在web.xml中对AListener进行配置。

1.4.4对各个监听器接口的方法中出现的类介绍

ServletContextAttributeEvent类:该类对象有三个方法,getSevletContext()用于返回一个ServletContext,getName()用于返回属性名,getValue()用于返回属性值。

HttpSessionBindingEvent类:该类对象有两个方法,getName()用于获取属性名,getValue()用于获取属性值。

ServletRequestAttributeEvent类:该类对象有两个方法,getName()用于获取属性名,getValue()用于获取属性值。

1.5感知监听器

保存在Session域中的对象可以有多种状态:绑定(session.setAttribute(“bean”,Object))到Session中,随Session对象持久化到一个存储设备中;从Session域中解除(session.removeAttribute(“bean”))绑定,随Session对象从一个存储设备中恢复。

Servlet 规范中定义了两个特殊的监听器接口”HttpSessionBindingListener和HttpSessionActivationListener”来帮助JavaBean 对象了解自己在Session域中的这些状态,实现这两个接口的类不需要 web.xml 文件中进行注册。

1.5.1HttpSessionBindingListener接口

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
17public class JavaBeanDemo1 implements HttpSessionBindingListener {
18
19 private String name;
20
21 @Override
22 public void valueBound(HttpSessionBindingEvent event) {
23 System.out.println(name+"被加到session中了");
24 }
25
26 @Override
27 public void valueUnbound(HttpSessionBindingEvent event) {
28 System.out.println(name+"被session踢出来了");
29 }
30
31 public String getName() {
32 return name;
33 }
34
35 public void setName(String name) {
36 this.name = name;
37 }
38
39 public JavaBeanDemo1(String name) {
40 this.name = name;
41 }
42 }

上述的JavaBeanDemo1这个javabean实现了HttpSessionBindingListener接口,那么这个JavaBean对象可以感知自己被绑定到Session中和从Session中删除的这两个操作。

1.5.2HttpSessionActivationListener接口

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

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

当绑定到HttpSession对象中的javabean对象将要随HttpSession对象被活化(反序列化)之后,web服务器调用该javabean对象的void sessionDidActive(HttpSessionEvent event)方法。这样javabean对象就可以知道自己将要和 HttpSession对象一起被反序列化(活化)回到内存中。(javabean随着HttpSession对象一起被活化的前提是该javabean对象除了实现该接口外还应该实现Serialize接口)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
27 public class JavaBeanDemo2 implements HttpSessionActivationListener,
28 Serializable {

29
30
31 private static final long serialVersionUID = 7589841135210272124L;
32 private String name;
33
34 @Override
35 public void sessionWillPassivate(HttpSessionEvent se) {
36
37 System.out.println(name+"和session一起被序列化(钝化)到硬盘了,session的id是:"+se.getSession().getId());
38 }
39
40 @Override
41 public void sessionDidActivate(HttpSessionEvent se) {
42 System.out.println(name+"和session一起从硬盘反序列化(活化)回到内存了,session的id是:"+se.getSession().getId());
43 }
44
45 public String getName() {
46 return name;
47 }
48
49 public void setName(String name) {
50 this.name = name;
51 }
52
53 public JavaBeanDemo2(String name) {
54 this.name = name;
55 }
56 }

既然这里谈到了session的序列化(钝化),反序列化(活化)那我们就来具体聊聊。

2.session序列化(钝化)

在session上线时,会在tomcat/work/Catalina/localhost/项目名/下生成一个sessions.ser文件,里面存放了所有session的信息,当你正在访问某个网页时若此时服务器关闭(关闭时才生成这个文件)又打开(打开后这个文件会消失),你依旧能正常访问该网页。(故说session有重生的效果)。
若想废掉session的序列化,需要在tomcat/conf/context.xml中添加<Manager pathname=“”/>

3.session的钝化与活化

Tomcat会在session一段时间内不被使用时钝化session对象,所谓钝化session,就是把session通过序列化的方法保存到硬盘文件中。当用户再使用session时,Tomcat还会把钝化的对象再活化session,所谓活化就是把硬盘文件中的session在反序列化中放回内存。当session被tomcat钝化时,sesseion中存储的对象也被钝化,当session被活化时,也会把session中存储的对象(javabean对象)活化。如果某个类(javabean对象)实现了HttpSessionActiveationListener接口后,当对象随着session被钝化和活化时,下面两个方法就会被调用:

public void sessionWillPassivate(HttpSessionEvent se):当对象感知被活化时调用本方法。  
public void sessionDidActivate(HttpSessionEvent se):当对象感知被钝化时调用本方法。

钝化时会在tomcat/work/Catalina/localhost/项目/mysession/文件下生成一个后缀为.session的文件,网页中一个被钝化的session就对应一个.session文件(而上面的序列化是一个.ser文件存在所有的session),在活化时此文件也不会消失(不同于上述的.ser文件消失)。
当然要看到上述效果,应该先配置tomcat钝化session的参数,在tomcat/conf/catalina/localhost目录下,添加以下配置内容(google一下吧)。

2018.3.19更

欢迎加入我的Java交流1群:659957958。

2018.4.21更:如果群1已满或者无法加入,请加Java学习交流2群:305335626

4.联系

If you have some questions after you see this article,you can tell your doubts in the comments area or you can find some info by clicking these links.

记得扫一扫领一下红包再走哦