1. 程式人生 > >第5章:作為Web應用:屬性和監聽者/5.2 Servlet監聽器

第5章:作為Web應用:屬性和監聽者/5.2 Servlet監聽器

  • 監聽器介面彙總

  1. 上下文相關
    1. 初始化完成或者銷燬監聽器:ServletContextListener
    2. 新增、刪除或者替換一個屬性監聽器:ServletContextAttributeListener(屬性相關)
  2. 會話有關:
    1. 跟蹤併發使用者數量、跟蹤活動的會話監聽器:HttpSessionListener
    2. 物件繫結到會話或者物件從會話刪除監聽器:HttpSessionBindingListener
    3. 物件所繫結的會話從一個JVM遷移到另外一個JVM時通知:HttpSessionActivationListener
    4. 增加、刪除或者替換一個會話屬性監聽器:HttpSessionAttributeListener(屬性相關)
  3. 請求相關:
    1. 請求到來時監聽器:ServletRequestListener
    2. 增加、刪除或者替換一個請求屬性監聽器:ServletRequestAttributeListener(屬性相關)
  • 上下文監聽器(ServletContextListener)--監聽器觸發時機

  1. ServletContextListener介面:
  2. 作用:在初始化ServletContext物件時觸發的一個事件,可用於在這個時刻建立一些全域性物件,比如資料庫連線物件。由於ServletContext初始化時Servlet還沒有形成,也就是不會接受外面的請求,所以該事件常用於在請求到來之前初始化一些物件
  3. 觸發時機:
    1. 容器在初始化完成ServletContext物件後
    2. 讀取web.xml檔案,如果發現監聽類實現了ServletContextListener介面(比如:MyServletContextListener類),則分別生成兩個物件
      1. 生成監聽類物件
        1. 類來源:使用者自定義類:比如 MyServletContextListener
        2. 類實現的介面:ServletContextListener
        3. 構造方法:預設無引數構造方法
      2. 生成事件類物件
        1. 類來源:容器自動生成
        2. 類實現的介面:ServletContextEvent
        3. 構造方法:引數為ServletContext物件的構造方法
  4. 觸發後效果:使用者自定義監聽類(比如:MyServletContextListener )就擁有了ServletContext物件,進而可以通過ServletContext物件設定某些屬性到上下文中
  • 上下文監聽器(ServletContextListener)--例項講解

  1. 例項操作
  2. 實體物件類
    package model;
    
    public class Dog {
       
       private String string;
       public Dog(String str){
    	   string = str;
       }
       public String getBeer(){
    	   return string;
       }
    }
    
    

     

  3. 實現ServletContextListener介面的類MyServletContextListener ,生成實體物件並儲存到ServletContext屬性中
    package listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import model.Dog;
    
    public class MyServletContextListener implements ServletContextListener{
    
    	@Override
    	public void contextInitialized(ServletContextEvent sce){
    		ServletContext servletContext =  sce.getServletContext();
    		Dog dog = new Dog(servletContext.getInitParameter("dog-desc"));
    		//設定servletContext屬性,在servlet類中可以獲取
    		servletContext.setAttribute("dog",  dog);
    		System.out.println("日誌測試:在建立完成servletContext時會觸發呼叫監聽類");
    	}
    	@Override
    	public void contextDestroyed(ServletContextEvent sce){
    		
    	}
    }
    
    

     

  4. 新建listenersc.html,跳轉到MyServletListener類的POST方法
    <html>
    <body>
    	<h1 align="center">Beer Selection Page</h1>
    	<form method="POST" action="MyServletListener.do">
    		Select beer characteristics
    		<p>
    			Color: <select name="color" size="1">
    				<option value="light">one</option>
    				<option value="amber">two</option>
    				<option value="write">three</option>
    				<option value="black">four</option>
    			</select> <br>
    			<br>
    		<center>
    			<input  type="SUBMIT">
    		</center>
    	</form>
    </body>
    </html>

     

  5. MyServletListenerTest類從ServletContext 屬性中獲取實體物件,並且回顯屬性到介面
    package web;
    
    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 model.Dog;
    
    public class MyServletListenerTest extends HttpServlet {
    
    	/**
    	 * Constructor of the object.
    	 */
    	public MyServletListenerTest() {
    		super();
    	}
    
    	/**
    	 * Destruction of the servlet. <br>
    	 */
    	public void destroy() {
    		super.destroy(); // Just puts "destroy" string in log
    		// Put your code here
    	}
    
    	/**
    	 * The doGet method of the servlet. <br>
    	 *
    	 * This method is called when a form has its tag value method equals to get.
    	 * 
    	 * @param request the request send by the client to the server
    	 * @param response the response send by the server to the client
    	 * @throws ServletException if an error occurred
    	 * @throws IOException if an error occurred
    	 */
    	public void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    		response.setContentType("text/html");
    		PrintWriter out = response.getWriter();
    		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    		out.println("<HTML>");
    		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    		out.println("  <BODY>");
    		out.print("    This is ");
    		out.print(this.getClass());
    		out.println(", using the GET method");
    		out.println("  </BODY>");
    		out.println("</HTML>");
    		out.flush();
    		out.close();
    	}
    
    	/**
    	 * The doPost method of the servlet. <br>
    	 *
    	 * This method is called when a form has its tag value method equals to post.
    	 * 
    	 * @param request the request send by the client to the server
    	 * @param response the response send by the server to the client
    	 * @throws ServletException if an error occurred
    	 * @throws IOException if an error occurred
    	 */
    	public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    		response.setContentType("text/html");
    		PrintWriter out = response.getWriter();
    		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    		out.println("<HTML>");
    		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    		out.println("  <BODY>");
    		out.print("    This is ");
    		out.print(this.getClass());
    		out.println(", using the POST method");
    		
    		//從ServletContext中獲取Dog的屬性並且列印在介面
    		ServletContext servletContext = getServletContext();
    		try {
    			Dog dog = (Dog)servletContext.getAttribute("dog");
    			String str = "";
    			str = dog.getBeer();
    			//列印Dog物件
    			out.println("Dog:" + str);
    		} catch (Exception e) {
    			// TODO: handle exception
    			System.out.println("獲取Dog物件失敗");
    		}
    		out.println("  </BODY>");
    		out.println("</HTML>");
    		out.flush();
    		out.close();
    	}
    
    	/**
    	 * Initialization of the servlet. <br>
    	 *
    	 * @throws ServletException if an error occurs
    	 */
    	public void init() throws ServletException {
    		// Put your code here
    	}
    
    }
    
    

     

  6. 配置web.xml
    <!-- 上下文設定 -->
    
         <context-param>
    
               <param-name>dog-desc</param-name>
    
               <param-value>my dog test</param-value>
    
         </context-param>
    
         
    
         <!-- 設定監聽類 -->
    
         <listener>
    
              <listener-class>listener.MyServletContextListener</listener-class>
    
         </listener>

     

  7. 測試:
    1. tomcat啟動的試試就進行了初始化
    2. 地址:http://localhost:8089/myWeb3/listenersc.html
    3. 結果:
  • 上下文屬性監聽器(ServletContextAttributeListener)--觸發時機:

  1. ServletContextAttributeListener介面: 
  2. 作用:監聽ServletContex物件的屬性增加、刪除、或者替換的觸發
  3. 觸發時機:當ServletContex物件呼叫以下幾個方法時都會觸發:
    1. 新增:public void setAttribute(String, Object)
    2. 刪除:public void removeAttribute(String)
    3. 替換:public void setAttribute(String, Object) 對重複的值就是替換
  4. 觸發結果:可獲取屬性的名稱,屬性的值對應的物件
  • 上下文屬性監聽器(ServletContextAttributeListener)--例項講解

  1. 定義類MyServletContextAttributeListener實現ServletContextAttributeListener介面
    package listener;
    
    import javax.servlet.ServletContextAttributeEvent;
    import javax.servlet.ServletContextAttributeListener;
    
    import model.Dog;
    
    public class MyServletContextAttributeListener implements ServletContextAttributeListener{
    
    	 public void attributeAdded(ServletContextAttributeEvent scab){
    		   System.out.println("attributeAdded:dog被這個方法呼叫時觸發:getServletContext().setAttribute"); 
    		   String name = scab.getName();
    		   if(name.equals("dog")){
    			   Dog dog = (Dog)scab.getValue();
    			   System.out.println("從新增屬性事件中獲取屬性物件:Dog,它的值是:"+ dog.getBeer());
    		   }
    		   
    	   }
    	   
    	   public void attributeRemoved(ServletContextAttributeEvent scab){
    		   System.out.println("attributeRemoved:dog被這個方法呼叫時觸發:getServletContext().RemoveAttribute"); 
    	   }
    	   
    	   public void attributeReplaced(ServletContextAttributeEvent scab){
    		   System.out.println("attributeReplaced:dog被這個方法呼叫時觸發:getServletContext().setAttribute"); 
    	   }
    }
    
    

     

  2. 從web.xml中定義監聽類
    <!-- 設定監聽類 -->
    
         <listener>
    
              <listener-class>listener.MyServletContextAttributeListener</listener-class>
    
         </listener>

     

  3. 測試重複呼叫ServletContext的setAttribute/removeAttribute方法,看觸發情況
    1. 方法呼叫:
      //設定servletContext屬性,在servlet類中可以獲取
      
                 servletContext.setAttribute("dog",  dog);
      
                 //這次應該是替換
      
                 servletContext.setAttribute("dog",  dog);
      
              //刪除屬性
      
                 servletContext.removeAttribute("dog");
      
                 //又新增屬性
      
                 servletContext.setAttribute("dog",  dog);

       

    2. 測試結果:

      attributeAdded:dog被這個方法呼叫時觸發:getServletContext().setAttribute

      從新增屬性事件中獲取屬性物件:Dog,它的值是:my dog test

      attributeReplaced:dog被這個方法呼叫時觸發:getServletContext().setAttribute

      attributeRemoved:dog被這個方法呼叫時觸發:getServletContext().RemoveAttribute

      attributeAdded:dog被這個方法呼叫時觸發:getServletContext().setAttribute

      從新增屬性事件中獲取屬性物件:Dog,它的值是:my dog test

      attributeAdded:dog被這個方法呼叫時觸發:getServletContext().setAttribute

  • 會話跟蹤監聽器(HttpSessionListener)---觸發時機

  1. HttpSessionListener介面:  
  2. 作用:新增會話或者銷燬會話的時候觸發
  3. 觸發時機:
    1. 新增會話:請求引數HttpServletRequest request呼叫 getSession() 方法時觸發新增會話
  4. 觸發結果:可進行會話儲存等操作

 

  • 會話跟蹤監聽器(HttpSessionListener)--例項講解

  1. 定義類MyHttpSessionListener實現HttpSessionListener介面
    package listener;
    
    import java.util.Enumeration;
    
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class MyHttpSessionListener implements HttpSessionListener {
    
    	@Override
    	public void sessionCreated(HttpSessionEvent se) {
    		// TODO Auto-generated method stub
    		
            HttpSession httpSession = se.getSession();
            
            System.out.println("新建立session:" + httpSession.getId());
            Enumeration<String> enumeration= httpSession.getAttributeNames();
            while(enumeration.hasMoreElements()){
            	System.out.println(enumeration.nextElement());
            }
    	}
    
    	@Override
    	public void sessionDestroyed(HttpSessionEvent se) {
    		// TODO Auto-generated method stub
    
    	}
    
    }
    
    

     

  2. 從web.xml中定義監聽類
    <!-- 設定會話建立/銷燬監聽類 -->
    
         <listener>
    
              <listener-class>listener.MyHttpSessionListener</listener-class>
    
         </listener>

     

  3. 測試在任何的servlet類中呼叫request.getSession()方法,只看到建立一個會話
    1. 從BeerSelect類中建立
      1. BeerSelect類的doPost方法獲取session
        System.out.println("======進來本介面即<<BeerSelect.java>>建立會話======");
                   request.getSession();
        

         

      2. 測試結果:

        ======進來本介面即<<BeerSelect.java>>建立會話======

        新建立session:3B82DAB9952B1100C22588E747B8ADEF

        ======進來本介面<<<MyServletListenerTest.java>>>即建立會話======

    2. 從MyServletListenerTest類中建立
      1. MyServletListenerTest類的doPost方法獲取session
        System.out.println("======進來本介面<<<MyServletListenerTest.java>>>即建立會話======");
        
                   request.getSession();

         

      2. 測試結果:

        ======進來本介面<<<MyServletListenerTest.java>>>即建立會話======

        新建立session:3DF0918D468CD76A25DFA94440CD2265

        ======進來本介面即<<BeerSelect.java>>建立會話======

 

  • 物件繫結到會話監聽器(HttpSessionBindingListener)--觸發時機

  1. HttpSessionBindingListener介面: 
  2. 作用:某個物件作為引數傳入session.setAttribute或者session.RemoveAttribute方法移除該物件時觸發該物件進行相關操作,
  3. 觸發時機:
    1. 新增會話:某個物件作為引數傳入session.setAttribute
    2. 刪除會話:session.RemoveAttribute方法移除該物件時觸發
  4. 觸發結果:比如把該物件儲存起來
  • 物件繫結到會話監聽器(HttpSessionBindingListener)--例項講解

  1. 自定義類MyHttpSessionBindingListener實現HttpSessionBindingListener介面
    package listener;
    
    import javax.servlet.http.HttpSessionBindingEvent;
    import javax.servlet.http.HttpSessionBindingListener;
    
    public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
    
    	private String strString ;
    	
    	public MyHttpSessionBindingListener(String str){
    		strString = str;
    	}
    	
    	@Override
    	public void valueBound(HttpSessionBindingEvent event) {
    		// TODO Auto-generated method stub
            System.out.println("MyHttpSessionBindingListener類被繫結:它的傳入引數為:"+
            		strString + "它的屬性名稱為:"+ event.getName());
    	}
    
    	@Override
    	public void valueUnbound(HttpSessionBindingEvent event) {
    		// TODO Auto-generated method stub
    		 System.out.println("MyHttpSessionBindingListener類被取消繫結:它的傳入引數為:"+
    	        		strString + "它的屬性名稱為:"+ event.getName());
    	}
    
    }
    
    

     

  2. 通過session.setAttribute方法設定自定義物件
    HttpSession session = request.getSession();
    
               System.out.println("<<BeerSelect.java>>設定屬性:");
    
               String name = "HttpSessionBindingListener——NAME";
    
               session.setAttribute(name, new MyHttpSessionBindingListener(" OKOKOK "));

     

  3. 通過session.RemoveAttribute方法取消自定義物件
    System.out.println("<<BeerSelect.java>>取消屬性:");
    
               session.removeAttribute(name);

     

  4. 測試:
    1. 設定時觸發繫結事件

      <<BeerSelect.java>>設定屬性:

      MyHttpSessionBindingListener類被繫結:它的傳入引數為: OKOKOK 它的屬性名稱為:HttpSessionBindingListener——NAME

    2. 取消時觸發取繫結事件

      <<BeerSelect.java>>取消屬性:

      MyHttpSessionBindingListener類被取消繫結:它的傳入引數為: OKOKOK 它的屬性名稱為:HttpSessionBindingListener——NAME

  5. 注意:如果被物件被重置,也就是屬性名稱不變,但是物件變了,這時候HttpSessionBindingListener會受到兩個事件,一個是繫結事件,另外一個是原物件的取消事件

》》》》》未完:易學筆記--Servlet和JSP--入門就看這一篇就夠了》》》》》