第六章 對象作用域與servlet事件監聽器


 
 
 
作用域對象
Servlet上下文監聽器
Servlet會話監聽器
Servlet請求監聽器
 
 
一:對象作用域

 

作用域對象

屬性操作方法

作用域范圍說明

ServletContext(上下文)

void setAttribute(String, Object)

Object getAttribute(Sting)

void removeAttribute(String)

Enumeration getAttributeNames()

整個Web應用程序

HttpSession(會話)

一個會話交互過程

ServletRequest(請求)

一次請求過程

1.1ServletContext應用上下文
例子:頁面訪問量的統計程序
主要的代碼塊:
 1         ServletContext sc=getServletContext();
 2         Integer count=(Integer)sc.getAttribute("counter");
 3         if(count==null){
 4             count=new Integer(1);
 5         }else{
 6             count=new Integer(count.intValue()+1);
 7         }        
 8         sc.setAttribute("counter", count);    
 9         resp.getWriter().print("該頁面被訪問的次數是:"+count);
10         resp.getWriter().close();

 

提示:上下文作用域中設置的屬性在整個Web應用中被共享,只要服務器不被關閉,Web應用中任何一部分都能訪問到該屬性。所以線程是不安全的。

1.2 HttpSession 會話作用域

例子:在線多人登錄

主要的代碼塊:

count

 1         PrintWriter pw=resp.getWriter();        
 2         ServletContext sc=getServletContext();
 3         HttpSession sess=req.getSession();
 4         String name = req.getParameter("username");
 5         List<String> userList=(List) getServletContext().getAttribute("userList");        
 6         if(userList==null){
 7             userList=new ArrayList<String>();
 8         }
 9         if(name!=null){
10             name=new String(name.getBytes("iso-8859-1"),"utf-8");
11             System.out.println("================="+name);
12             userList.add(name);
13             sess.setAttribute("username",name);
14             getServletContext().setAttribute("userList", userList);
15             req.getRequestDispatcher("/count1").forward(req, resp);
16             
17         }
18         else{
19             pw.print("<html>");
20             pw.print("<head></head>");
21             pw.print("<body><h1>在線書店登錄</h1>");
22             pw.print("<form action='/day13/count'>");
23             pw.print("username:<input type='text' name='username'/><br/>");
24             pw.print("<input type='submit' value='submit'/></form></body>");
25             pw.print("</html>");            
26         }
27         pw.flush();
28         pw.close();
29         

 

 count1

 1  PrintWriter pw=resp.getWriter();          
 2           HttpSession sess=req.getSession();
 3           List<String> userList=(List) getServletContext().getAttribute("userList");
 4           String name=(String) sess.getAttribute("username");
 5           String action=req.getParameter("action");
 6           if(action==null){
 7                pw.print("用戶"+name+"歡迎你!【<a href='count1?action=loginout'>注銷</a>】<br/>");
 8                Iterator<String> i=userList.iterator();
 9                while(i.hasNext()){
10                    String name1=i.next();
11                    pw.print("<p>當前用戶有:"+name1+"</p>");
12                }
13                
14           }else if(action.equals("loginout")){
15               sess.invalidate();
16               userList.remove(name);
17               getServletContext().setAttribute("userList", userList);
18               
19           }        
20         

 

    
 
提示:每一個會話只能訪問當前會話作用域中設置的屬性。但是當我們使用特殊的瀏覽器窗口打開方式使用相同的Session來訪問該設置的屬性。也就是說多個線程訪問相同的會話屬性。所以線程也是不安全的。
 
1.3  ServletRequest 請求作用域
系統的資源消耗
屬性可以保存在請求作用域范圍中
 
 
 
二:監聽器概述
監聽session,request,application這三個對象里存取數據的變化
監聽器對象可以在事情發生前、發生后可以做一些必要的處理
Servlet監聽器主要目的是給Web應用增加事件處理機制,以便更好地監視和控制Web應用的狀態變化
      Servlet監聽器接口和相對應的監聽器事件類

事件類型

描述

Listener接口

ServletContext   事件

生命周期

Servlet上下文剛被創建並可以開始為第一次請求服務,或者Servlet上下文將要被關閉發生的事件

ServletContextListener

屬性改變

Servlet上下文內的屬性被增加、刪除或者替換時發生的事件

ServletContextAttributeListener

HttpSession    事件

生命周期

HttpSession被創建、無效或超時時發生

HttpSessionListener

HttpSessionActivationListener

會話遷移

HttpSession被激活或鈍化時發生

屬性改變

在HttpSession中的屬性被增加、刪除、替換時發生

HttpSessionAttributeListener

HttpSessionBindingListener

對象綁定

對象被綁定到或者移出HttpSession時發生。

ServletRequest   事件

生命周期

在Servletr請求開始被Web組件處理時發生

ServletRequestListener

屬性改變

在ServletRequest對象中的屬性被增加、刪除、替換時發生

ServletRequestAttributeListener

 

三:監聽Web應用程序范圍內的事件

Web應用啟動和銷毀事件
Web應用程序的屬性發生改變的事件(包括增加、刪除、修改)。
定義了ServletContextListener和ServletContextAttributeListener兩個接口

監聽器需要在web.xml定義監聽器: 

<listener>
         <listener-class>com.cy.listener.servletContext</listener-class>
</listener>

1)ServletContextListener接口的方法如下:
例子:由監聽器管理共享數據庫連接
 1 package com.cy.listener;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 
 7 import javax.servlet.ServletContextEvent;
 8 import javax.servlet.ServletContextListener;
 9 
10 public class ServletContext implements ServletContextListener {
11 
12     @Override
13     public void contextDestroyed(ServletContextEvent arg0) {
14         //應用程序被銷毀
15         try {
16             Connection c=(Connection) arg0.getServletContext().getAttribute("connection");
17             c.close();
18         } catch (SQLException e) {
19             
20             e.printStackTrace();
21         }
22         
23     }
24 
25     @Override
26     public void contextInitialized(ServletContextEvent arg0) {
27         //應用程序被加載及初始化
28          try {
29              //連接數據庫
30             Class.forName("com.mysql.jdbc.Driver");
31             Connection con=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/books","root","root");
32             arg0.getServletContext().setAttribute("connection", con);
33         } catch (Exception e) {
34             e.printStackTrace();
35         }
36          
37     }
38 
39 }

 2)ServletContextAttributeListener接口方法:

 1 package com.cy.listener;
 2 
 3 import javax.servlet.ServletContextAttributeEvent;
 4 import javax.servlet.ServletContextAttributeListener;
 5 
 6 public class MyServletContext implements ServletContextAttributeListener {
 7 
 8     @Override
 9     public void attributeAdded(ServletContextAttributeEvent event) {
10         System.out.println("添加一個ServletContext屬性"+event.getName()+"========="+event.getValue());//回傳屬性的名稱  值
11     }
12 
13     @Override
14     public void attributeRemoved(ServletContextAttributeEvent event) {
15         System.out.println("刪除一個ServletContext屬性"+event.getName()+"========="+event.getValue());
16     }
17 
18     @Override
19     public void attributeReplaced(ServletContextAttributeEvent event) {
20         System.out.println("某個ServletContext屬性被改變"+event.getName()+"========="+event.getValue());
21     }
22 
23 }

 

 1 package com.cy.listener;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServlet;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 
10 public class Test extends HttpServlet{
11     
12     private static final long serialVersionUID = 1L;
13 
14     @Override
15     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
16             throws ServletException, IOException {
17         resp.setContentType("text/html;charset=utf-8");
18         getServletContext().setAttribute("username", "tiger");
19         getServletContext().setAttribute("username", "kitty");
20         getServletContext().removeAttribute("username");        
21     }
22     
23     @Override
24     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
25             throws ServletException, IOException {
26         doPost(req, resp);
27     }
28 
29 }

 結果:

添加一個ServletContext屬性username=========tiger
某個ServletContext屬性被改變username=========tiger
刪除一個ServletContext屬性username=========kitty

四:監聽會話范圍內事件
1)HttpSessionBindingListener接口
注意:HttpSessionBindingListener接口是唯一不需要在web.xml設定的listener;
當我們的類實現了HttpSessionBindingListener接口后,只要這個對象加入Session范圍(即調用HttpSession對象的setAttribute方法的時候)或從Session對象移出(即調用HttpSession對象的removeAttribute方法的時候或Session超時時)容器就會通知這個對象,分別會自動調用下列兩個方法:
–void valueBound(HttpSessionBindingEvent event):當對象正在綁定到Session中,Servlet容器調用該方法來通知該對象
–void valueUnbound(HttpSessionBindingEvent event):當從Session中刪除對象時,Servlet容器調用該方法來通知該對象

HttpSessionBindingEvent類提供如下方法:

public String getName():返回綁定到Session中或從Session中刪除的屬性名字。

public Object getValue():返回被添加、刪除、替換的屬性值

public HttpSession getSession():返回HttpSession對象

 
 
2)HttpSessionAttributeListener接口
監聽HttpSession中的屬性的操作
–當在Session中增加一個屬性時,激發attributeAdded(HttpSessionBindingEvent event) 方法;
–當在Session刪除一個屬性時,激發attributeRemoved(HttpSessionBindingEvent event)方法;
–當在Session屬性被重新設置時,激發attributeReplaced(HttpSessionBindingEvent event) 方法。 
 
 3)HttpSessionListener接口
監聽HttpSession對象的創建和銷毀操作
-當創建一個Session時,激發session Created(HttpSessionEvent event)方法
–當銷毀一個Session時,激發sessionDestroyed (HttpSessionEvent event)方法
例子:可用於在線人數的統計
主要代碼:
 1 package com.cy;
 2 
 3 public class OnlineCounter {
 4     private static int online=0;
 5     
 6     public static int getOnlie(){
 7         return online;        
 8     }
 9     public static void raise(){
10         online++;
11     }
12     public static void reduce(){
13         online--;
14     }
15 
16 }
17 
18 
19 package com.cy;
20 
21 import javax.servlet.http.HttpSessionEvent;
22 import javax.servlet.http.HttpSessionListener;
23 
24 public class OnlineConter  implements HttpSessionListener{
25 
26     @Override
27     public void sessionCreated(HttpSessionEvent arg0) {
28         OnlineCounter.raise();    
29     }
30     @Override
31     public void sessionDestroyed(HttpSessionEvent arg0) {
32       OnlineCounter.reduce();        
33     }
34 
35 }
36 
37 
38 package com.cy;
39 
40 import java.io.IOException;
41 
42 import javax.servlet.ServletException;
43 import javax.servlet.http.HttpServlet;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46 import javax.servlet.http.HttpSession;
47 
48 public class TestServlet extends HttpServlet {
49     @Override
50     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
51             throws ServletException, IOException {
52         resp.setContentType("text/html;charset=utf-8");
53         HttpSession sess=req.getSession();
54         sess.setMaxInactiveInterval(10);
55         resp.getWriter().print("當前在線人數為:"+OnlineCounter.getOnlie());        
56     }
57     
58     @Override
59     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
60             throws ServletException, IOException {
61         doPost(req, resp);
62     }
63     
64 
65 }

 

五:監聽請求生命周期內事件

請求作用域范圍內的生命周期事件用於管理整個request生命周期的狀態和資源
ServletRequestListener接口
–public void requestDestroyed(ServletRequestEvent event):當請求被銷毀時被處理。
–public void requestInitialized(ServletRequestEvent event):當請求被創建時被處理
ServletRequestAttributeListener接口
–public void attributeAdded(ServletRequestAttributeEvent event) :當在請求作用域中添加一個屬性的時候調用該方法。
–public void attributeRemoved(ServletRequestAttributeEvent event) :當在請求作用域中刪除一個屬性時調用
–public void attributeReplaced(ServletRequestAttributeEvent event) :當在請求作用域中替換一個屬性值的時候調用
 
總結:
1 在Servlet中3個對象作用域分別由ServletContext、ServletRequest和HttpSession接口來處理
2 上下文作用域中設置的屬性是線程不安全的
3 對於同一個客戶的多個請求,Session會跨這些請求持久存儲
4 設置在上下文和會話作用域中的對象,會非常消耗系統的資源
5 請求作用域范圍僅僅作用在與一個請求相關的兩個資源之間
6 應用程序事件監聽器是實現一到多個Servlet事件監聽器接口的類。它們在Web應用程序部署的時候,被Web容器初始化和注冊
7 ServletContext監聽器用於管理應用程序JVM級別保存的資源或狀態。
8 HTTP會話監聽器用於管理從同一客戶端或用戶發送的一系列請求的資源或狀態。
9 Request請求監聽器用於管理Request請求生命周期內的狀態  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM