1. 程式人生 > >監聽request session servletContext的建立與銷燬

監聽request session servletContext的建立與銷燬

監聽器:

 * Java Web的三大元件:Servlet、Listener、Filter.
 * 注意:
   * listener的觸發或呼叫,是不需要我們關注的.(Tomcat伺服器)
   * Tomcat與JavaEE的版本是有對應的.
     * Tomcat 7.0版本 - Servlet 3.0
     * Tomcat 6.0版本 - Servlet 2.5
   * 開發原則:不要追新.
   * Listener對於我們來講:如何編寫.

 * 八大監聽器:

   * 第一組:用於監聽Servlet三個域物件的建立與銷燬
     * ServletRequestListner
     * HttpSessionListener

     * ServletContextListener

             * 作用:用於監聽Servlet三個域物件的建立與銷燬.
                  * 三個域物件的建立與銷燬:
                             * Request物件:
                                 * 建立:發生請求時.
                                 * 銷燬:請求完成時.
                            * Session物件:
                                   * 建立:發生請求時,並且執行getSession()語句.
                                  * 銷燬:執行Session的銷燬方法invalidate().
                          * ServletContext物件:
                                   * 建立:Tomcat啟動時.
                                  * 銷燬:Tomcat關閉時.

package app.java.listener1;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 用於測試HttpSessionListener監聽器.
 *  * 實現HttpSessionListener介面.
 *  * 重寫該介面提供的所有方法.
 * @author JYL
 */
public class HttpSessionListenerTest implements HttpSessionListener,ServletRequestListener,ServletContextListener {

	/**
	 * sessionCreated(HttpSessionEvent arg0)
	 *  * 該方法用於監聽Session物件的建立.
	 *  * 問題:應該是在Session物件建立之前還是之後被呼叫?後.
	 *  * 作用:可以實現必要的初始化工作.
	 */
	public void sessionCreated(HttpSessionEvent arg0) {
		System.out.println("我的Session物件終於被建立啦。。。");
		/*
		 * HttpSessionEvent事件物件:
		 *  * 獲取對應的Request物件.
		 *  * 獲取對應的ServletContext物件.
		 */
	}
	/**
	 * sessionDestroyed(HttpSessionEvent arg0)
	 *  * 該方法用於監聽Session物件的銷燬.
	 *  * 問題:應該是在Session物件銷燬之前還是之後被呼叫?前.
	 *  * 作用:可以實現必要的資源釋放工作.
	 */
	public void sessionDestroyed(HttpSessionEvent arg0) {
		System.out.println("我的Session物件離我而去啦。。。");
	}
	public void contextDestroyed(ServletContextEvent arg0) {
		
	}
	public void contextInitialized(ServletContextEvent arg0) {
		
	}
	public void requestDestroyed(ServletRequestEvent arg0) {
		
	}
	public void requestInitialized(ServletRequestEvent arg0) {
		
	}

}
因為是屬於servlet ,所以要在web.xml中進行配置:
 <!-- 在web.xml檔案中如何配置Listener -->
  <!-- 
  <listener>
  	<listener-class>app.java.listener1.HttpSessionListenerTest</listener-class>
  </listener>
   <listener>
  	<listener-class>app.java.listener2.ServletRequestAttributeListenerTest</listener-class>
  </listener> 
  -->
  <listener>
  	<listener-class>app.java.listener.demo.MyServletContextListener</listener-class>
  </listener>
  <listener>
  	<listener-class>app.java.listener.demo.MyHttpSessionListener</listener-class>
  </listener>

jsp頁面:

<%
	HttpSession mysession = request.getSession();
	mysession.invalidate();
%>

   * 第二組:用於監聽Servlet三個域物件的屬性變化(設定、刪除、修改)
     * ServletRequestAttributeListener
     * HttpSessionAttributeListener

     * ServletContextAttributeListener

package app.java.listener2;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
/**
 * 用於測試ServletRequestAttributeListener監聽器.
 * @author JYL
 *
 */
public class ServletRequestAttributeListenerTest implements ServletRequestAttributeListener {
	/**
	 * attributeAdded()
	 *  * 該方法用於監聽Request物件新增屬性.
	 */
	public void attributeAdded(ServletRequestAttributeEvent arg0) {
		System.out.println("Request物件添加了一個屬性。。。");
	}
	/**
	 * attributeRemoved()
	 *  * 該方法用於監聽Request物件刪除屬性.
	 */
	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
		System.out.println("Request物件刪除了一個屬性。。。");
	}
	/**
	 * attributeReplaced()
	 *  * 該方法用於監聽Request物件修改屬性.
	 */
	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
		System.out.println("Request物件修改了一個屬性。。。");
	}

}

jsp頁面:
<%

	request.setAttribute("yttlj", "zhouzhiruo");
	request.removeAttribute("yttlj");
%>

 * 如何自定義監聽器:

           * 第一步:
                    * 建立Java類,實現上述八個監聽器介面之一.
                     * 重寫該介面提供的所有方法.
           * 第二步:
                    * 在web.xml檔案中配置Listener.
                   <listener>
                       <listener-class>自定義Listener的完整路徑</listener-class>
                   </listener>
   * 第三組:用於通知被繫結到Session物件的屬性.

     * HttpSessionBindingListener

   * 注意:
     * 該監聽器應該由JavaBean類實現.(可以將JavaBean繫結到Session上) 繫結什麼java物件都可以
     * 誰被繫結到Session上,誰就實現該監聽器.
     * 該監聽器的作用:通知被繫結到Session的JavaBean物件.
     * 使用該監聽器時,不需要在web.xml檔案中進行配置的. 

JavaBean:

package app.java.listener3;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

/**
 * 定義一個User的JavaBean.
 *  * 將該JavaBean物件繫結到Session中.
 *  * 該JavaBean實現HttpSessionBindingListener.
 *  
 * 問題:
 *  * 當JavaBean實現了HttpSessionBindingListener介面.
 *  * 汙染了當前JavaBean.
 *    * 由監聽器提供了多餘的方法,不屬於JavaBean.
 *    * JavaBean說白了就是Java類,與JavaEE是無關的.
 *    * 一旦實現HttpSessionBindingListener介面,就與JavaEE是有關的.
 * 
 * 最終建議:不建議使用.
 * @author JYL
 */
public class User implements HttpSessionBindingListener {

	private int id;
	private String name;
	private String job;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	/**
	 * valueBound(HttpSessionBindingEvent arg0)
	 *  * 該方法用於監聽當前JavaBean被繫結到Session中.
	 *  * 執行session.setAttribute()方法時,就是繫結.
	 */
	public void valueBound(HttpSessionBindingEvent arg0) {
		System.out.println("這個JavaBean被成功地包養了。。。");
	}
	/**
	 * valueUnbound(HttpSessionBindingEvent arg0)
	 *  * 該方法用於監聽當前JavaBean從Session中解綁.
	 *  * 執行session.removeAttribute()方法時,就是解綁.
	 */
	public void valueUnbound(HttpSessionBindingEvent arg0) {
		System.out.println("這個JavaBean被無情地拋棄啦。。。");
	}
	
}


BeanServlet.java:

package app.java.listener3;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class BeanServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		//1 例項化JavaBean
		User user = new User();
		user.setId(1);
		user.setName("zhangwuji");
		user.setJob("jiaozhu");
		HttpSession session = request.getSession();
		//2 將該JavaBean的例項,繫結到Session物件中
		session.setAttribute("user", user);
		//3 從Session物件中刪除JavaBean物件
		session.removeAttribute("user");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}


  * 第四組:用於監聽Session的鈍化與活化

     * HttpSessionActivationListener

   * Session的序列化
     * 當Tomcat伺服器正常關閉後,Session會自動被儲存到本地硬碟中.
       * 在Tomcat伺服器的安裝目錄:%Catalina_HOME%\work\Catalina\localhost\Web工程名目錄中.
     * 當Tomcat伺服器正常啟動後,Session會自動從本地硬碟中讀取到記憶體中.
       * 儲存在本地硬碟中的序列化檔案,自動銷燬.
     * 問題:

       * Tomcat伺服器為什麼提供這麼一個機制?

建立一個Servlet用於向Session中存放資料內容。

package app.java.listener4;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class SessionServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		User user = new User();
		user.setId(1);
		user.setName("zhangwuji");
		user.setJob("jiaozhu");
		//1 獲取或建立Session物件
		HttpSession session = request.getSession();
		//2 向Session物件設定屬性內容
		session.setAttribute("user", user);
		//3 將session中的內容響應到頁面中
		response.setContentType("text/html;charset=utf-8");
		response.getWriter().println("成功地向Session放置了內容.");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}


建立一個Servlet用於從Session中讀取存放的資料內容。

package app.java.listener4;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class GetSessionServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		HttpSession session = request.getSession();
		User user = (User)session.getAttribute("user");
		System.out.println(user);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

在bean中監聽:
package app.java.listener4;

import java.io.Serializable;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;

/**
 * 定義一個User的JavaBean.
 * 
 * @author JYL
 */
public class User implements HttpSessionActivationListener,Serializable {

	private int id;
	private String name;
	private String job;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", job=" + job + "]";
	}
	public void sessionDidActivate(HttpSessionEvent arg0) {
		System.out.println("Session成功地從火星迴來啦。。。");
	}
	public void sessionWillPassivate(HttpSessionEvent arg0) {
		System.out.println("Session成功地逃離地球啦。。。");
	}
	
}

  * Session的鈍化與活化      * 實現步驟:
       * 1編寫Servlet設定Session.
       *2 在Tomcat安裝目錄%Catalina_HOME%\conf\Catalina\localhost目錄中,建立一個名為Web工程名的xml檔案.
       
 <?xml version="1.0" encoding="UTF-8"?>
    <Context>
          <!-- maxIdleSwap:指定多長時間後Session會被鈍化.(單位為分鐘) -->
        <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1" >
           <!-- 
               directory:指定鈍化檔案的儲存目錄.
               鈍化檔案儲存路徑:${CATALINA_HOME}\work\Catalina\localhost\Web工程名\${sessionid}.session
           -->
          <Store className="org.apache.catalina.session.FileStore" directory="mysession" />
         </Manager>
     </Context>


      * 3建立JavaBean,用於繫結到Session中.
        * 該JavaBean實現了HttpSessionActivationListener介面,並且重寫該介面提供的所有方法.

        * 該JavaBean實現了Serializable(序列化)介面(Session的鈍化與活化是基於Session的序列化實現的)

      * Session鈍化與活化和序列化的區別:
       * Session序列化:
               * Tomcat提供的自動機制.
               * Session的序列化檔案在重新被使用時,消失.
       * Session鈍化與活化:
               * 手動實現.
              * Session的鈍化檔案並不消失.
 * 擴充套件:
   * Servlet的三大域物件:
     * Request物件 - 一次請求
     * Session物件 - 一次會話
     * ServletContext物件 - Tomcat從啟動到關閉
   * JSP的四大域物件:
     * page物件 - 當前頁面
     * Request物件
     * Session物件
     * ServletContext物件

案例:

統計線上人數:


1.建立ServletContextListener監聽器完成線上人數的初始化:

package app.java.listener.demo;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {
	/**
	 * 完成線上人數統計的初始化工作.
	 */
	public void contextInitialized(ServletContextEvent sce) {
		//因為這個監聽器拿不到session,所以就把線上人數放到ServletContext中。
		ServletContext context = sce.getServletContext();
		context.setAttribute("sums", 0);
	}
	
	public void contextDestroyed(ServletContextEvent arg0) {}

}


2.建立HttpSessionListener

package app.java.listener.demo;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyHttpSessionListener implements HttpSessionListener {
	/**
	 * 建立Session表示人數增加一個.
	 *  * 在該方法中,獲取ServletContext物件.
	 *  * 修改ServletContext物件的"sums"屬性值.(+1)
	 *  * 將修改後的"sums"屬性值,重新放回去.
	 */
	public void sessionCreated(HttpSessionEvent se) {
		ServletContext context = se.getSession().getServletContext();
		int sums = (Integer)context.getAttribute("sums");
		sums = sums + 1;
		context.setAttribute("sums", sums);
	}
	/**
	 * 銷燬Session表示人數減少一個.
	 *  * 在該方法中,獲取ServletContext物件.
	 *  * 修改ServletContext物件的"sums"屬性值.(-1)
	 *  * 將修改後的"sums"屬性值,重新放回去.
	 */
	public void sessionDestroyed(HttpSessionEvent se) {
		ServletContext context = se.getSession().getServletContext();
		int sums = (Integer)context.getAttribute("sums");
		sums = sums - 1;
		context.setAttribute("sums", sums);
	}

}

3.建立一個servlet顯示線上人數:
package app.java.listener.demo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 * 當前servlet用於測試統計線上人數
 * @author JYL
 */
public class DemoServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("test/html charset = utf-8");

		HttpSession session = request.getSession();
		session.setAttribute("mingjiao", "zhangwuji");
		System.out.println("人數增加了");
		
		// 將統計的線上人數顯示在客戶端頁面 線上人數放在了servletContext裡面
		//1 獲取servletContext物件
		ServletContext context = getServletContext();
		
		//2 從servletContext物件中,獲取線上統計人數
		int sums = (Integer)context.getAttribute("sums");
		
		//3 將線上統計人數響應到客戶端頁面
		response.setContentType("text/html;charset=utf-8");
		response.getWriter().println("當前線上人數為:"+sums);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}


配置xml:

<listener>
  	<listener-class>app.java.listener.demo.MyServletContextListener</listener-class>
  </listener>
  <listener>
  	<listener-class>app.java.listener.demo.MyHttpSessionListener</listener-class>
  </listener>