監聽: 對某一些操作進行監視,那麼就稱爲監聽
在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 的超時時間