監聽
監聽: 對某一些操作進行監視,那麼就稱為監聽
在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 id。
現在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>
當然: 也可以根據自己的情況修改,例如:将本想買中的逾時時間修改為1 分鐘
// 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 的逾時時間