listener监听器主要用于监听request,application,session三大作用域对象的创建以及这些对象的属性的增加,修改以及删除等各种变化。
(一)servletContextListener
-
1.ServletContext作为Servlet三大域对象的应用 request、session、application(ServletContext)之一。
-
2.ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。
-
3.request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。
-
4.获取servletcontext对象: ServletContext sc = null;
sc = request.getSession().getServletContext(); //或者使用 //ServletContext sc = this.getServletContext();
System.out.println(“sc=” + sc); -
5.ServletContext 与application的异同 相同:其实servletContext和application 是一样的,就相当于一个类创建了两个不同名称的变量。
不同:两者的区别就是application用在jsp中,servletContext用在servlet中。 -
6.在 Servlet API 中有一个 ServletContextListener 接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。 当Servlet 容器启动或终止Web
应用时,会触发ServletContextEvent 事件,该事件由 ServletContextListener 来处理。在
ServletContextListener 接口中定义了处理ServletContextEvent 事件的两个方法。 -
contextInitialized(ServletContextEvent sce) :当Servlet 容器启动Web
应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化,并且对那些在Web 应用启动时就需要被初始化的Servlet
进行初始化。 -
contextDestroyed(ServletContextEvent sce) :当Servlet 容器终止Web
应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器。 -
7.ServletContextListener的使用场景一般为:一般用于启动Web应用时完成一些初始化的操作,如初始化Web.xml里的配置参数,连接数据库等。
-
8.下面是一个ServletContextListener的Demo,主要用于解决启动程序时获取客户端绝对路径的问题。在启动时获取Web.xml文件的初始化参数。
public class MyservletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
String contextPath=arg0.getServletContext().getContextPath(); //=="/servletContextListenerDemo"
System.out.println("==================全局对象已销毁!=================="+contextPath);
arg0.getServletContext().setAttribute("root", contextPath); //等同于application对象
}
//用于完成一些启动程序时的参数初始化操作
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
String contextPath=arg0.getServletContext().getContextPath(); //=="/servletContextListenerDemo"
System.out.println("==================全局对象已创建!=================="+contextPath);
arg0.getServletContext().setAttribute("root", contextPath); //等同于application对象
}
}
<listener>
<listener-class>listener.MyservletContextListener</listener-class>
</listener>
<body>
<h2> ${root }</h2>
<form action="${root }/Myservlet" >
用户名<input type="text" name="username"><br>
密码 <input type="text" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
(二) ServletContextAttributeListener
ServletContextAttributeListener用于监听ServletContext(application)范围内属性的变化,当application范围内的属性被添加删除,替换时,这些对应的监听器将会被触发。
实现该接口的监听器需要实现如下三个方法:
1.attributeAdded(ServletContextAttributeEvent event):当程序把一个属性存入application范围时触发该方法。
2.attributeRemoved(ServletContextAttributeEvent event):当程序把一个属性从application范围删除时触发该方法。
3.attributeReplaced(ServletContextAttributeEvent event):当程序替换application范围内的属性时将触发该方法。
以下为ServletContextAttributeListener的一个Demo:
public class Myservletcontextattribute implements ServletContextAttributeListener{
//application属性的增加
public void attributeAdded(ServletContextAttributeEvent arg0) {
ServletContext application=arg0.getServletContext();
//获取添加的属性名和属性值
String name=arg0.getName();
Object value=arg0.getValue();
System.out.println(application+"范围内添加了名为"+name+"值为"+value+"的属性");
}
//applicable属性的删除
public void attributeRemoved(ServletContextAttributeEvent arg0) {
ServletContext application=arg0.getServletContext();
//获取删除的属性名和属性值
String name=arg0.getName();
Object value=arg0.getValue();
System.out.println(application+"范围内名为"+name+"值为"+value+"的属性被删除了");
}
//application属性的修改
public void attributeReplaced(ServletContextAttributeEvent arg0) {
ServletContext application=arg0.getServletContext();
//获取修改的属性名和属性值
String name=arg0.getName();
Object value=arg0.getValue();
System.out.println(application+"范围内名为"+name+"值为"+value+"的属性被修改了");
}
}
<%
//往application域对象中添加属性
application.setAttribute("name", "中国特色社会主义!");
//替换application域对象中name属性的值
application.setAttribute("name", "Java web 从门到精通");
//移除application域对象中name属性
application.removeAttribute("name");
%>
(三)ServletRequestAttributeListener
- 与ServletContextAttributeListener相似,ServletRequestAttributeListener用于监听request域范围内属性的变化,当request域范围内的属性被添加删除,替换时,这些对应的监听器将会被触发。它同样有以下3个抽象方法。
1.attributeAdded(ServletRequestAttributeEvent event):当程序把一个属性存入request范围时触发该方法。
2.attributeRemoved(ServletRequestAttributeEvent event):当程序把一个属性从request范围删除时触发该方法。
3.attributeReplaced(ServletRequestAttributeEvent event):当程序替换request范围内的属性时将触发该方法。
public class MyservletrequestattributeListener implements ServletRequestAttributeListener {
//request属性增加
public void attributeAdded(ServletRequestAttributeEvent arg0) {
System.out.println("request域添加了属性:" + arg0.getName() + "=" + arg0.getValue());
}
//request属性删除
public void attributeRemoved(ServletRequestAttributeEvent arg0) {
System.out.println("request域删除了属性:" + arg0.getName() + "=" + arg0.getValue());
}
//request属性修改
public void attributeReplaced(ServletRequestAttributeEvent arg0) {
System.out.println("request域修改了属性(这里展示的是被替换的):" + arg0.getName() + "=" + arg0.getValue());
}
}
<%
request.setAttribute("key", "中国特色社会主义!");
request.setAttribute("key", "Java Web");
request.removeAttribute("key");
%>
(四)ServletRequestListener
- ServletRequestListener监听器用于监听Request对象的创建与销毁。
- ServletRequestListener监听器可以非常方便地监听到每次请求的创建、销毁,因此Web应用可通过实现该接口的监听器来监听访问该应用的每个请求,从而实现系统日志。
- 实现该接口需要实现以下两个方法:
public class ServletRequestListenerDemo implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
//请求被销毁时调用的方法
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
//请求被创建时的方法
}
}
ServletRequestListener监听器可以用于统计Web应用的访问量。以下是一个简单的用于统计Web应用的浏览量的Demo:
public class MyservletrequestListener implements ServletRequestListener{
//请求对象的创建
public void requestDestroyed(ServletRequestEvent arg0) {
System.out.println("请求对象已创建" + "," + new Date());
Object count = arg0.getServletContext().getAttribute("count");
Integer cInteger = 0;
if (count != null) {
cInteger = Integer.valueOf(count.toString());
}
System.out.println("历史访问次数::" + count);
cInteger++;
arg0.getServletContext().setAttribute("count", cInteger);
}
//请求对象的销毁
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("请求对象已销毁" + "," + new Date());
System.out.println("当前访问次数:" + arg0.getServletContext().getAttribute("count"));
}
}
(五) httpSessionListener
- 如果用户长时间没有访问服务器,超过了会话最大超时时间,服务器就会自动销毁超时的session。
- 会话超时时间可以在web.xml中进行设置,为了容易看到超时效果,我们将超时时间设置为最小值。
<session-config> <session-timeout>1</session-timeout> </session-config>
-
时间单位是一分钟,并且只能是整数,如果是零或负数,那么会话就永远不会超时。
-
实现该接口需要实现以下两个方法,分别对应于Session的创建和失效:
-
public void sessionCreated(HttpSessionEvent se); public void
sessionDestroyed(HttpSessionEvent se); -
httpSessionListener监听器可以用于统计和收集在线用户的信息,站中经常需要进行在线人数的统计。过去的一般做法是结合登录和退出功能,即当用户输入用户名密码进行登录的时候计数器加1,然后当用户点击退出按钮退出系统的时候计数器减1。这种处理方式存在一些缺点,例如:用户正常登录后,可能会忘记点击退出按钮,而直接关闭浏览器,导致计数器减1的操作没有及时执行;网站上还经常有一些内容是不需要登录就可以访问的,在这种情况下也无法使用上面的方法进行在线人数统计。
-
以下是一个简单的demo,可用于统计在线用户人数:
public class httpsessionlistener implements HttpSessionListener{
//session对象的创建
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("会话对象创建" + "," + new Date());
Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
Integer count = 0;
if (lineCount == null) {
lineCount = "0";
}
count = Integer.valueOf(lineCount.toString());
count++;
System.out.println("新上线一人,当前在线人数有: " + count + " 个");
arg0.getSession().getServletContext().setAttribute("lineCount", count);
}
//session对象的销毁
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("会话对象销毁" + "," + new Date());
Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
Integer count = Integer.valueOf(lineCount.toString());
count--;
System.out.println("一人下线,当前在线人数: " + count + " 个");
arg0.getSession().getServletContext().setAttribute("lineCount", count);
}
}
<listener>
<listener-class>listener.httpsessionlistener</listener-class>
</listener>
<session-config>
<session-timeout>1</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
(六) httpSessionBindingListener
- 1.HttpSessionBindingListener接口介绍 ,如果一个对象实现了HttpSessionBindingListener接口,当这个对象被绑定到Session中或者从session中被删除时,Servlet容器会通知这个对象,而这个对象在接收到通知后,可以做一些初始化或清除状态的操作。
- 2.该监听器可以解决一些不同用户登陆同一浏览器和同一用户登陆不同浏览器等问题。使用场合可以是一些购物车失效的时候,触发该事件,保存到数据库中,下次打开相应的网站购物车信息还在。
- 3.该接口实现了两个方法,分别是: valueBound()当实现了该接口的对象被绑定到session对象中触发。调用setAttribute();方法。
valueUnbound()当实现了该接口的对象被移除出了session对象中触发。触发该方法有三种可能,
调用removeAttribute()方法,第二次调用setAttribute()方法替代原来的对象,调用session.invalidate()方法或session对象超时失效。 - 以下这个Demo把它的session最长发呆时间设为1:
public class userOnlineListener implements HttpSessionBindingListener {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void valueBound(HttpSessionBindingEvent arg0) {
//监听对象绑定到session对象中
System.out.println("用户"+name+"登录了"+new Date());
}
public void valueUnbound(HttpSessionBindingEvent arg0) {
//监听对象从session中移除
System.out.println("用户"+name+"下线了"+new Date());
}
}
<%
userOnlineListener user=new userOnlineListener();
user.setName(session.getId());
session.setAttribute("user", user);
%>
(七)httpSessionAttributeListener
- HttpSessionAttributeListener是SessionAttribute的监听,当在会话对象中加入属性、移除属性或替换属性时,就会调用HttpSessionAttributeListener监听器。可以和HttpSessionBindingEvent合作着使用。
- 该接口实现了以下三个方法:
public voidattributeAdded(HttpSessionBindingEvent se):在session中添加对象时触发此操作
public voidattributeRemoved(HttpSessionBindingEvent se):修改、删除session中添加对象时触发此操作
public voidattributeReplaced(HttpSessionBindingEvent se):在Session属性被重新设置时
public class Myhtttpsessionattributelistener implements HttpSessionAttributeListener{
public void attributeAdded(HttpSessionBindingEvent arg0) {
// session属性增加
System.out.println("session域添加了属性:" + arg0.getName() + "=" + arg0.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent arg0) {
// session属性删除
System.out.println("session域删除了属性:" + arg0.getName() + "=" + arg0.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent arg0) {
// session属性修改
System.out.println("session域修改了属性(这里展示的是被替换的):" + arg0.getName() + "=" + arg0.getValue());
}
}
<%
session.setAttribute("key", "广州商学院");
session.setAttribute("key", "廖明强");
session.removeAttribute("key");
%>
tips:httpSessionBindingListener与httpSessionAttributeListener的区别:
- 1.只有实现httpSessionBindingListener该接口的对象,保存到session中,或者从session中移除时,才会触发该事件,其他没有实现该接口的对象保存或者移除到session时不会触发该事件。
- 2.而对于httpSessionAttributeListener监听器是监听session对象中各种属性的变化,无论他是否实现了什么接口,无论它是否为一个对象,只要当它的属性发生变化,都会触发该事件。
(八) HttpSessionActivationListener
-
1.用户访问的时候,假如服务器突然关闭了,这个时候,用户的session就不存在了,假如是购物网站,也就相当于,用户好不容易选好的物品,刚刚添加到购物车,结果,因为服务器的突然关闭一下,什么都没了,这样很不好,于是我们就需要实现会话的持久化。可以让我们在重新启动服务器之后用户的session还在服务器中存在!
即用户session的东西还全部在。
因为我们服务器在关闭的时候把用户的session存储到硬盘了(钝化),在重新启动服务器之后,我们又从硬盘中恢复到内存中! -
2.把对象转化位字节序列的过程称为序列化(保存到硬盘,持久化)
-
把字节序列转化位对象的过程称为反序列化(存放于内存)
-
用途: 把对象的字节序列永久保存到硬盘上,通常放到一个文件中。 把网络传输的对象通过字节序列化,方便传输。
-
3…HttpSessionActivationListener用于监控实现类本身,当实现类对象被添加到session中(session.setAttribute())后,session对象序列化(钝化)前和反序列化(活化)后都会被执行,相应的方法。
sessionWillPassivate(HttpSessionEvent se) session钝化前执行(session从内存到硬盘)
sessionDidActivate(HttpSessionEvent se) session活化后执行(session从硬盘到内存)
public class MysessionActivation implements HttpSessionActivationListener,Serializable{
private static final long serialVersionUID = -8367567842003252055L;
private String name ;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public MysessionActivation(String name) {
this.name = name;
}
//对象实例化后保存到session中,当session失效要被序列化前执行,(只有保存到session中的对象才会被监听到)
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println(name + "=>Session被序列化到(钝化)到硬盘中,SessionId是:"+se.getSession().getId());
}
//当session被反序列化后执行
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println(name + "=>Session被反序列化到(活化)到内存中,SessionId是:"+se.getSession().getId());
}
}
<body bgcolor="cyan">
This is my JSP page. <br>
<%
MysessionActivation bb=new MysessionActivation("广州商学院");
session.setAttribute("key", bb);
%>
</body>
总结:
servletContextListener、httpSessionListener、servletRequestListener。 这三个接口写法上实际是差不多的,都有两个分别代表了该域对象创建时调用和销毁时调用的方法,据我的理解,这三个对象最大的区别应该就是作用域不一样。 servletContext在整个应用启动到结束中生效,启动系统时创建这个对象,整个过程中这个对象是唯一的。 httpSession则是在一个session会话中生效,在一个session被创建直到失效的过程中都起作用,不过一个启动的应用中httpSession对象可以有多个,比如同一台电脑两个浏览器访问,就会创建两个httpSession对象。 而servletRequest是在一个request请求被创建和销毁的过程中生效,每发起一次请求就会创建一个新的servletRequest对象,比如刷新浏览器页面、点击应用的内链等等。