监听: 对某一些操作进行监视,那么就称为监听
在web 中的监听主要的功能是永远对ServletContext、Session、Request进行监听的一种操作
1、对application 进行监听
Application是Servlet 进行监听接口的对象,表示的是整个上下午的环境
如果要想实现对application 监听则可以使用如下两个接口
ServletContextListener 是对整个上下文环境的监控
ServletContextAttributeListener 对属性的监听
- package org.gz.servlet.listener;
- import javax.servlet.*;
- public class ServletContextListener implements ServleContextListener {
- public void contextInitialized(ServletContextEvent event) {
- System.out.println("========容器初始化--->" + event.getServletContext().getContextPath());
- }
- public void contextDestroyed(ServletContextEvent event) {
- System.out.println("=====容器销毁 ----->"+ event.getServletContext().getContextPath());
- }
- }
过滤器: <filter> 、<filter-mapping>
但是现在的监听器就省事了,直接编写<listener>
如果现在一个web.xml文件之中包含简单Servlet 、过滤器、监听器,则建议的缩写配置的顺序
<filter>
<filter-mapping>
<listener>
<servlet>
<servlet-mapping>
监听器的配置
- <listener>
- <listener-class>
- org.gz.servlet.listener.ServletContextListenerdemo
- </listener-class>
- </listener
还可以实现 ServletContextAttributeListener 接口,此接口可以直接对属性监听
- package org.gz.servlet.listener.attribute;
- import javax.servlet.*;
- public class ServletContextAttributeListenerdemo implements ServletContextAttributeListener {
- public void attributeAdded(ServletContextAttributeEvent scab) {
- System.out.println("增加属性名称--》" + scab.getName() + " ,属性内容————》" + scab.getValue());
- }
- public void attributeRemoved(ServletContextAttributeEvent scab) {
- System.out.println("删除属性名称--》" + scab.getName() + " ,属性内容————》" + scab.getValue());
- }
- public void attributeReplaced(ServletContextAttributeEvent scab) {
- System.out.println("替换属性名称--》" + scab.getName() + " ,属性内容————》" + scab.getValue());
- }
- }
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- this.getServletContext().setAttribute("info","www.baidu.com");
- %>
- </body>
- </html>
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- this.getServletContext().removeAttribute("info");
- %>
- </body>
- </html>
监听器就是实现接口,覆写方法, 实际上这个与SWING中的操作都是非常类似的
2、对session 监听
在监听器中,针对于session的监听操作提供了三个接口:
HttpSessionListener
HttpSessionAttributeListener
HttpSessionBindingListener
Session 属于HTTP协议的范畴,所以这些接口肯定在javax.servlet.http 包中定义的。
在Servlet中如果要想取得session 依靠HttpServletRequest 接口中的getSession()方法
- package org.gz.servlet.sesssionlistener;
- import javax.servlet.http.*;
- // org.gz.servlet.sesssionlistener.HttpSessionListenerDemo
- public class HttpSessionListenerDemo implements HttpSessionListener {
- public void sessionCreated(HttpSessionEvent se) {
- System.out.println("session创建,SESSION ID= " + se.getSession().getId());
- }
- public void sessionDestroyed(HttpSessionEvent se) {
- System.out.println("session销毁,SESSION ID= " + se.getSession().getId());
- }
- }
- /*
- <listener>
- <listener-class>
- org.gz.servlet.sesssionlistener.HttpSessionListenerDemo
- </listener-class>
- </listener>
- */
现在session 已经被创建,在第一次访问的时候触发了事件,可是还有一点,什么时候销毁呢?
如果现在想要让一个session 销毁的化,有两种方法,但是这两种方法并不是直接关闭服务器就可以实现的:
session注销: invalidate()
超时时间到了, 在tomcat中一般的超时时间是30 分钟。
- //D:\java rj\web\tomcat-6.0.18\conf\web.xml
- <session-config>
- <session-timeout>30</session-timeout>
- </session-config>
- // E:\webdemo\WEB-INF\web.xml
- <session-config>
- <session-timeout>1</session-timeout>
- </session-config>
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- // 手工注销
- session.invalidate();
- %>
- </body>
- </html>
之前一直强调,当调用invalidate() 方法的时候就意味着 session 的内容将被清空
不过一般的销毁时间都是设置在30 分钟或更长的时间,如果时间保存长也就意味着占用空间的时间就长
- package org.gz.servlet.attributelistener;
- import javax.servlet.http.*;
- // org.gz.servlet.attributelistener.HttpSessionAttributeListenerdemo
- public class HttpSessionAttributeListenerdemo implements HttpSessionAttributeListener {
- public void attributeAdded(HttpSessionBindingEvent se) {
- System.out.println(se.getSession().getId() + " ,增加属性--->名称: " +
- se.getName() + ", 属性内容: " + se.getValue() );
- }
- public void attributeRemoved(HttpSessionBindingEvent se) {
- System.out.println(se.getSession().getId() + " ,删除属性--->名称: " +
- se.getName() + ", 属性内容: " + se.getValue() );
- }
- public void attributeReplaced(HttpSessionBindingEvent se) {
- System.out.println(se.getSession().getId() + " ,替换属性--->名称: " +
- se.getName() + ", 属性内容: " + se.getValue() );
- }
- }
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- // 手工注销
- session.removeAttribute("info");
- %>
- </body>
- </html>
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- // 手工注销
- session.setAttribute("info","www.baidu.com");
- %>
- </body>
- </html>
- package org.gz.servlet.bindinglistener;
- import javax.servlet.http.*;
- // org.gz.servlet.bindinglistener.HttpSessionBindingListenerdemo
- public class HttpSessionBindingListenerdemo implements HttpSessionBindingListener {
- private String name;
- public HttpSessionBindingListenerdemo (String name) {
- this.name = name;
- }
- public void valueBound(HttpSessionBindingEvent event) {
- System.out.println("在session中保存HttpSessionBindingListenerdemo 对象(name = "
- + this.getName() + " ) , session id = " + event.getSession().getId());
- }
- public void valueUnbound(HttpSessionBindingEvent event) {
- System.out.println("在session中移除HttpSessionBindingListenerdemo 对象(name = "
- + this.getName() + " ) , session id = " + event.getSession().getId());
- }
- public String getName() {
- return this.name;
- }
- public void setName(String name){
- this.name = name;
- }
- }
- /*
- 此处根本就不需要任何配置文件的支持
- */
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <%@ page import="org.gz.servlet.bindinglistener.*"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- //由于此处需要手工绑定,所以才不需要做任何额外的配置 移除 session.removeAttribute("info");
- HttpSessionBindingListenerdemo binding = new HttpSessionBindingListenerdemo("gz");
- session.setAttribute("info",binding); //直接保存 HttpSessionBindingListenerdemo 对象
- %>
- </body>
- </html>
3、对request监听
在Servlet 2.4 之后增加了对request 操作的监听,主要使用 ServletRequestListener、 ServletRequestAttributeListener 两个接口
- package org.gz.servlet.reqestlistener;
- import javax.servlet.*;
- public class ServletRequestListenerdemo implements ServletRequestListener {
- public void requestInitialized(ServletRequestEvent sre) {
- System.out.println("request 初始化 http://" +
- sre.getServletRequest().getRemoteAddr() +
- sre.getServletContext().getContextPath());
- }
- public void requestDestroyed(ServletRequestEvent sre) {
- System.out.println("request 销毁 http://" +
- sre.getServletRequest().getRemoteAddr() +
- sre.getServletContext().getContextPath());
- }
- }
- package org.gz.servlet.reqestattributelistener;
- import javax.servlet.*;
- public class ServletRequestAttributeListenerdemo implements ServletRequestAttributeListener {
- public void attributeAdded(ServletRequestAttributeEvent srae) {
- System.out.println("增加request属性-->属性名称: " + srae.getName() + ",属性内容: " + srae.getValue());
- }
- public void attributeRemoved(ServletRequestAttributeEvent srae) {
- System.out.println("删除request属性-->属性名称: " + srae.getName() + ",属性内容: " + srae.getValue());
- }
- public void attributeReplaced(ServletRequestAttributeEvent srae) {
- System.out.println("替换request属性-->属性名称: " + srae.getName() + ",属性内容: " + srae.getValue());
- }
- }
- /*
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <%@ page import="org.gz.servlet.bindinglistener.*"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- request.setAttribute("info","www.baidu.com");
- //request.setAttribute("info","www.baidu.com"); //将出现替换
- request.removeAttribute("info");
- %>
- </body>
- </html>
- <listener>
- <listener-class>
- org.gz.servlet.reqestattributelistener.ServletRequestAttributeListenerdemo
- </listener-class>
- </listener>
- */
从实际来讲,对request 范围的监听操作并不是很常见的,用的最多的还是ServletContext、HttpSession监听
4、监听器的实例
经常会在各个站点上看见一些在线人员的列表操作,实际上次操作就可以通过监听完成
在整个的操作中,需要使用以下几个接口 :
所有的人员列表应该用集合保存,但是这个集合所有的用户都可以看见,而且以后也要操作,
那么证明在整个监听中必然需要有一个 application 对象保存
用户登录成功,增加属性,肯定要在属性监听接口中使用
当用户离开之后,
- package org.gz.servlet.context;
- import java.util.*;
- import javax.servlet.*;
- import javax.servlet.http.*;
- // org.gz.servlet.context.OnlineUserList
- public class OnlineUserList implements ServletContextListener,HttpSessionAttributeListener,HttpSessionListener {
- private ServletContext app = null;
- //ServletContextListener
- public void contextInitialized(ServletContextEvent sce) {
- this.app = sce.getServletContext(); //初始化
- this.app.setAttribute("online",new TreeSet()); //设置内容,准备集合 TreeSet 按照 Comparable 二分法排序
- }
- public void contextDestroyed(ServletContextEvent sce) { }
- // HttpSessionAttributeList
- public void attributeAdded(HttpSessionBindingEvent se) {
- Set all = (Set) this.app.getAttribute("online"); // 取出属性集合
- all.add(se.getValue()); // 保存属性名字
- this.app.setAttribute("online",all); // 重新设置回去
- }
- public void attributeRemoved(HttpSessionBindingEvent se) {
- Set all = (Set) this.app.getAttribute("online");
- all.remove(se.getSession().getAttribute("userid")); //用户离开删除
- this.app.setAttribute("online",all);
- }
- public void attributeReplaced(HttpSessionBindingEvent se) { }
- // HttpSessionListener
- public void sessionCreated(HttpSessionEvent se) { }
- public void sessionDestroyed(HttpSessionEvent se) {
- Set all = (Set) this.app.getAttribute("online");
- all.remove(se.getSession().getAttribute("userid")); //用户离开删除 没有getValue()这个方法
- this.app.setAttribute("online",all); //操作完了之后重新放回集合之中
- }
- }
- /*
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <%
- request.setCharacterEncoding("GBK");
- %>
- <body>
- <form action="online_listener.jsp" method="post">
- 用户ID: <input type="text" name="userid">
- <input type="submit" value="登录">
- </form>
- <%
- String userid = request.getParameter("userid");
- if(!(userid == null || "".equals(userid))) { //userid 不为空
- session.setAttribute("userid",userid);
- response.sendRedirect("online_list.jsp");
- }
- %>
- </body>
- </html>
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <%@ page import="java.util.*"%>
- <html>
- <head> <title>欢迎光临</title>
- </head>
- <body>
- <%
- Set all = (Set)this.getServletContext().getAttribute("online");
- Iterator iter = all.iterator();
- while(iter.hasNext()) {
- %>
- <h3><%=iter.next()%></h3>
- <%
- }
- %>
- </body>
- </html>
- */
- /*
- <listener>
- <listener-class>
- org.gz.servlet.context.OnlineUserList
- </listener-class>
- </listener>
- <session-config>
- <session-timeout>1</session-timeout>
- </session-config>
- E:\webdemo\WEB-INF\classes>javac -d . *.java
- 注意:OnlineUserList.java 使用了未经检查或不安全的操作。
- 注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。 (编译出现这样的情况是由于List集合没有加泛型)
- */
使用监听器可以对application 、session、request 的属性范围进行监听
在web 中可以配置每一个session 的超时时间