轉自:http://www.cnblogs.com/xdp-gacl/p/3969249.htmlhtml
域對象中屬性的變動的事件監聽器就是用來監聽 ServletContext, HttpSession, HttpServletRequest 這三個對象中的屬性變動信息事件的監聽器。
這三個監聽器接口分別是ServletContextAttributeListener, HttpSessionAttributeListener 和ServletRequestAttributeListener,這三個接口中都定義了三個方法來處理被監聽對象中的屬性的增長,刪除和替換的事件,同一個事件在這三個接口中對應的方法名稱徹底相同,只是接受的參數類型不一樣。java
當向被監聽對象中增長一個屬性時,web容器就調用事件監聽器的attributeAdded方法進行響應,這個方法接收一個事件類型的參數,監聽器能夠經過這個參數來得到正在增長屬性的域對象和被保存到域中的屬性對象
各個域屬性監聽器中的完整語法定義爲:web
1 public void attributeAdded(ServletContextAttributeEvent scae) 2 public void attributeReplaced(HttpSessionBindingEvent hsbe) 3 public void attributeRmoved(ServletRequestAttributeEvent srae)
當刪除被監聽對象中的一個屬性時,web容器調用事件監聽器的attributeRemoved方法進行響應
各個域屬性監聽器中的完整語法定義爲:apache
1 public void attributeRemoved(ServletContextAttributeEvent scae) 2 public void attributeRemoved (HttpSessionBindingEvent hsbe) 3 public void attributeRemoved (ServletRequestAttributeEvent srae)
當監聽器的域對象中的某個屬性被替換時,web容器調用事件監聽器的attributeReplaced方法進行響應
各個域屬性監聽器中的完整語法定義爲:tomcat
1 public void attributeReplaced(ServletContextAttributeEvent scae) 2 public void attributeReplaced (HttpSessionBindingEvent hsbe) 3 public void attributeReplaced (ServletRequestAttributeEvent srae)
編寫ServletContextAttributeListener監聽器監聽ServletContext域對象的屬性值變化狀況,代碼以下:服務器
1 package me.gacl.web.listener; 2 3 import java.text.MessageFormat; 4 5 import javax.servlet.ServletContextAttributeEvent; 6 import javax.servlet.ServletContextAttributeListener; 7 8 /** 9 * @ClassName: MyServletContextAttributeListener 10 * @Description: ServletContext域對象中屬性的變動的事件監聽器 11 * @author: 孤傲蒼狼 12 * @date: 2014-9-11 下午10:53:04 13 * 14 */ 15 public class MyServletContextAttributeListener implements 16 ServletContextAttributeListener { 17 18 @Override 19 public void attributeAdded(ServletContextAttributeEvent scab) { 20 String str =MessageFormat.format( 21 "ServletContext域對象中添加了屬性:{0},屬性值是:{1}" 22 ,scab.getName() 23 ,scab.getValue()); 24 System.out.println(str); 25 } 26 27 @Override 28 public void attributeRemoved(ServletContextAttributeEvent scab) { 29 String str =MessageFormat.format( 30 "ServletContext域對象中刪除屬性:{0},屬性值是:{1}" 31 ,scab.getName() 32 ,scab.getValue()); 33 System.out.println(str); 34 } 35 36 @Override 37 public void attributeReplaced(ServletContextAttributeEvent scab) { 38 String str =MessageFormat.format( 39 "ServletContext域對象中替換了屬性:{0}的值" 40 ,scab.getName()); 41 System.out.println(str); 42 } 43 }
在web.xml文件中註冊監聽器session
1 <listener> 2 <description>MyServletContextAttributeListener監聽器</description> 3 <listener-class>me.gacl.web.listener.MyServletContextAttributeListener</listener-class> 4 </listener>
編寫ServletContextAttributeListenerTest.jsp測試頁面app
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML> 3 <html> 4 <head> 5 <title>ServletContextAttributeListener監聽器測試</title> 6 </head> 7 8 <body> 9 <% 10 //往application域對象中添加屬性 11 application.setAttribute("name", "孤傲蒼狼"); 12 //替換application域對象中name屬性的值 13 application.setAttribute("name", "gacl"); 14 //移除application域對象中name屬性 15 application.removeAttribute("name"); 16 %> 17 </body> 18 </html>
運行結果以下:dom
從運行結果中能夠看到,ServletContextListener監聽器成功監聽到了ServletContext域對象(application)中的屬性值的變化狀況。jsp
編寫監聽器監聽HttpSession和HttpServletRequest域對象的屬性值變化狀況,代碼以下:
1 package me.gacl.web.listener; 2 3 import java.text.MessageFormat; 4 5 import javax.servlet.ServletRequestAttributeEvent; 6 import javax.servlet.ServletRequestAttributeListener; 7 import javax.servlet.http.HttpSessionAttributeListener; 8 import javax.servlet.http.HttpSessionBindingEvent; 9 10 public class MyRequestAndSessionAttributeListener implements 11 HttpSessionAttributeListener, ServletRequestAttributeListener { 12 13 @Override 14 public void attributeAdded(ServletRequestAttributeEvent srae) { 15 String str =MessageFormat.format( 16 "ServletRequest域對象中添加了屬性:{0},屬性值是:{1}" 17 ,srae.getName() 18 ,srae.getValue()); 19 System.out.println(str); 20 } 21 22 @Override 23 public void attributeRemoved(ServletRequestAttributeEvent srae) { 24 String str =MessageFormat.format( 25 "ServletRequest域對象中刪除屬性:{0},屬性值是:{1}" 26 ,srae.getName() 27 ,srae.getValue()); 28 System.out.println(str); 29 } 30 31 @Override 32 public void attributeReplaced(ServletRequestAttributeEvent srae) { 33 String str =MessageFormat.format( 34 "ServletRequest域對象中替換了屬性:{0}的值" 35 ,srae.getName()); 36 System.out.println(str); 37 } 38 39 @Override 40 public void attributeAdded(HttpSessionBindingEvent se) { 41 String str =MessageFormat.format( 42 "HttpSession域對象中添加了屬性:{0},屬性值是:{1}" 43 ,se.getName() 44 ,se.getValue()); 45 System.out.println(str); 46 } 47 48 @Override 49 public void attributeRemoved(HttpSessionBindingEvent se) { 50 String str =MessageFormat.format( 51 "HttpSession域對象中刪除屬性:{0},屬性值是:{1}" 52 ,se.getName() 53 ,se.getValue()); 54 System.out.println(str); 55 } 56 57 @Override 58 public void attributeReplaced(HttpSessionBindingEvent se) { 59 String str =MessageFormat.format( 60 "HttpSession域對象中替換了屬性:{0}的值" 61 ,se.getName()); 62 System.out.println(str); 63 } 64 }
在web.xml文件中註冊監聽器
1 <listener> 2 <description>MyRequestAndSessionAttributeListener監聽器</description> 3 <listener-class>me.gacl.web.listener.MyRequestAndSessionAttributeListener</listener-class> 4 </listener>
編寫RequestAndSessionAttributeListenerTest.jsp測試頁面
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML> 3 <html> 4 <head> 5 <title>RequestAndSessionAttributeListener監聽器測試</title> 6 </head> 7 8 <body> 9 <% 10 //往session域對象中添加屬性 11 session.setAttribute("aa", "bb"); 12 //替換session域對象中aa屬性的值 13 session.setAttribute("aa", "xx"); 14 //移除session域對象中aa屬性 15 session.removeAttribute("aa"); 16 17 //往request域對象中添加屬性 18 request.setAttribute("aa", "bb"); 19 //替換request域對象中aa屬性的值 20 request.setAttribute("aa", "xx"); 21 //移除request域對象中aa屬性 22 request.removeAttribute("aa"); 23 %> 24 </body> 25 </html>
運行結果以下:
從運行結果中能夠看到,HttpSessionAttributeListener監聽器和ServletRequestAttributeListener成功監聽到了HttpSession域對象和HttpServletRequest域對象的屬性值變化狀況。
保存在Session域中的對象能夠有多種狀態:綁定(session.setAttribute("bean",Object))到Session中;從 Session域中解除(session.removeAttribute("bean"))綁定;隨Session對象持久化到一個存儲設備中;隨Session對象從一個存儲設備中恢復
Servlet 規範中定義了兩個特殊的監聽器接口"HttpSessionBindingListener和HttpSessionActivationListener"來幫助JavaBean 對象瞭解本身在Session域中的這些狀態: ,實現這兩個接口的類不須要 web.xml 文件中進行註冊。
實現了HttpSessionBindingListener接口的JavaBean對象能夠感知本身被綁定到Session中和 Session中刪除的事件
當對象被綁定到HttpSession對象中時,web服務器調用該對象的void valueBound(HttpSessionBindingEvent event)方法
當對象從HttpSession對象中解除綁定時,web服務器調用該對象的void valueUnbound(HttpSessionBindingEvent event)方法
範例:
1 package me.gacl.domain; 2 3 import javax.servlet.http.HttpSessionBindingEvent; 4 import javax.servlet.http.HttpSessionBindingListener; 5 6 /** 7 * @ClassName: JavaBeanDemo1 8 * @Description: 9 * 實現了HttpSessionBindingListener接口的 JavaBean對象能夠感知本身被綁定到 Session中和從Session中刪除的事件 10 當對象被綁定到 HttpSession 對象中時,web 服務器調用該對象的 void valueBound(HttpSessionBindingEvent event) 方法 11 當對象從 HttpSession 對象中解除綁定時,web 服務器調用該對象的 void valueUnbound(HttpSessionBindingEvent event)方法 12 13 * @author: 孤傲蒼狼 14 * @date: 2014-9-11 下午11:14:54 15 * 16 */ 17 public 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 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%@page import=" me.gacl.domain.JavaBeanDemo1"%> 3 <!DOCTYPE HTML> 4 <html> 5 <head> 6 <title></title> 7 </head> 8 9 <body> 10 <% 11 //將javabean對象綁定到Session中 12 session.setAttribute("bean",new JavaBeanDemo1("孤傲蒼狼")); 13 //從Session中刪除javabean對象 14 session.removeAttribute("bean"); 15 %> 16 </body> 17 </html>
運行結果以下:
實現了HttpSessionActivationListener接口的JavaBean對象能夠感知本身被活化(反序列化)和鈍化(序列化)的事件
當綁定到HttpSession對象中的javabean對象將要隨HttpSession對象被鈍化(序列化)以前,web服務器調用該javabean對象的void sessionWillPassivate(HttpSessionEvent event) 方法。這樣javabean對象就能夠知道本身將要和HttpSession對象一塊兒被序列化(鈍化)到硬盤中.
當綁定到HttpSession對象中的javabean對象將要隨HttpSession對象被活化(反序列化)以後,web服務器調用該javabean對象的void sessionDidActive(HttpSessionEvent event)方法。這樣javabean對象就能夠知道本身將要和 HttpSession對象一塊兒被反序列化(活化)回到內存中
範例:
1 package me.gacl.domain; 2 3 import java.io.Serializable; 4 5 import javax.servlet.http.HttpSessionActivationListener; 6 import javax.servlet.http.HttpSessionEvent; 7 8 /** 9 * @ClassName: JavaBeanDemo2 10 * @Description: 11 實現了HttpSessionActivationListener接口的 JavaBean 對象能夠感知本身被活化和鈍化的事件 12 活化:javabean對象和Session一塊兒被反序列化(活化)到內存中。 13 鈍化:javabean對象存在Session中,當服務器把session序列化到硬盤上時,若是Session中的javabean對象實現了Serializable接口 14 那麼服務器會把session中的javabean對象一塊兒序列化到硬盤上,javabean對象和Session一塊兒被序列化到硬盤中的這個操做稱之爲鈍化 15 若是Session中的javabean對象沒有實現Serializable接口,那麼服務器會先把Session中沒有實現Serializable接口的javabean對象移除 16 而後再把Session序列化(鈍化)到硬盤中 17 當綁定到 HttpSession對象中的javabean對象將要隨 HttpSession對象被鈍化以前, 18 web服務器調用該javabean對象對象的 void sessionWillPassivate(HttpSessionEvent event)方法 19 這樣javabean對象就能夠知道本身將要和 HttpSession對象一塊兒被序列化(鈍化)到硬盤中 20 當綁定到HttpSession對象中的javabean對象將要隨 HttpSession對象被活化以後, 21 web服務器調用該javabean對象的 void sessionDidActive(HttpSessionEvent event)方法 22 這樣javabean對象就能夠知道本身將要和 HttpSession對象一塊兒被反序列化(活化)回到內存中 23 * @author: 孤傲蒼狼 24 * @date: 2014-9-11 下午11:22:35 25 * 26 */ 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 }
爲了觀察綁定到HttpSession對象中的javabean對象隨HttpSession對象一塊兒被鈍化到硬盤上和從硬盤上從新活化回到內存中的的過程,咱們須要藉助tomcat服務器幫助咱們完成HttpSession對象的鈍化和活化過程,具體作法以下:
在WebRoot\META-INF文件夾下建立一個context.xml文件,以下所示:
context.xml文件的內容以下:
1 <Context> 2 <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> 3 <Store className="org.apache.catalina.session.FileStore" directory="gacl"/> 4 </Manager> 5 </Context>
在context.xml文件文件中配置了1分鐘以後就將HttpSession對象鈍化到本地硬盤的一個gacl文件夾中
jsp測試代碼以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%@page import="me.gacl.domain.JavaBeanDemo2"%> 3 <!DOCTYPE HTML> 4 <html> 5 <head> 6 <title></title> 7 </head> 8 9 <body> 10 一訪問JSP頁面,HttpSession就建立了,建立好的Session的Id是:${pageContext.session.id} 11 <hr/> 12 <% 13 session.setAttribute("bean",new JavaBeanDemo2("孤傲蒼狼")); 14 %> 15 </body> 16 </html>
訪問這個jsp頁面,服務器就會立刻建立一個HttpSession對象,而後將實現了HttpSessionActivationListener接口的JavaBean對象綁定到session對象中,這個jsp頁面在等待1分鐘以後沒有人再次訪問,那麼服務器就會自動將這個HttpSession對象鈍化(序列化)到硬盤上,
咱們能夠在tomcat服務器的work\Catalina\localhost\JavaWeb_Listener_20140908\gacl文件夾下找到序列化到本地存儲的session,以下圖所示:
當再次訪問這個Jsp頁面時,服務器又會自動將已經鈍化(序列化)到硬盤上HttpSession對象從新活化(反序列化)回到內存中。運行結果以下:
JavaWeb開發技術中的監聽器技術的內容就這麼多了,在平時的工做中,監聽器技術在JavaWeb項目開發中用得是比較多,所以必須掌握這門技術。