Servlet的生命週期(重點)

有關servlet的類有Servlet,HttpServlet以及GenericServlet.
其實我們要寫一個Servlet只要寫一個類去實現Servlet就可以了,但是,Servlet裏面有很多的方法,我們沒有必要每次爲了寫一個Servlet而去實現這麼多方法,所以這裏提供了一個GenericServlet,這個類實現了一些方法,我們可以直接繼承這個類還不用去實現Servlet,但是我們要做的web,GenericServlet裏面並沒有有關協議的一些方法,所以,我們要再寫一個類,這個類裏面要有有關協議的方法,這個類就是HttpServlet,裏面有doGet()和doPost()方法

Servlet—>GenericServlet—>HttpServlet

我們正式講servlet的生命週期。

4.1 引入

Servlet的生命週期: servlet類對象什麼時候創建,什麼時候調用什麼方法,什麼時候銷燬。參照下例:

以前的對象: new Student(); stu.study(); stu=null;

注意Servlet程序的生命週期由tomcat服務器控制的!

4.2 Servlet重要的四個生命週期方法

構造方法: 創建servlet對象的時候調用。默認情況下,第一次訪問servlet的時候創建servlet對象,只調用1次。證明servlet對象在tomcat是單實例的。

init方法: 創建完servlet對象的時候調用。只調用1次。

service方法: 每次發出請求時調用。調用n次。

destroy方法: 銷燬servlet對象的時候調用。停止服務器或者重新部署web應用時銷燬servlet對象。只調用1次。

4.3 僞代碼演示servlet的生命週期

下面的d代碼都是在Tomcat內部做的。

Tomtcat內部代碼運行:

1)通過映射找到到servlet-class的內容,字符串: gz.itcast.a_servlet.FirstServlet

2)通過反射構造FirstServlet對象

  a、得到字節碼對象

Class clazz = class.forName(“gz.itcast.a_servlet.FirstServlet”);

b、調用無參數的構造方法來構造對象

Object obj = clazz.newInstance(); —1.servlet的構造方法被調用

3)創建ServletConfig對象,通過反射調用init方法

  a、得到方法對象

Method m = clazz.getDeclareMethod(“init”,ServletConfig.class);
//上述代碼的意思是:“init”是方法的名字,ServletConfig.class是init方法要傳入的參數的類型。

//m其實就是init方法,並且傳入的參數類型是Servletonfig.class;

b、 調用方法

m.invoke(obj,config); –2.servlet的init方法被調用

//上面代碼的意思是:由obj(上面已經生成好了)這個對象去調用init這個方法,傳入config這個實參(之前說的形參是ServletConfig.class),這裏的config就是一個//ServletConfig對象
4)創建request,response對象,通過反射調用service方法

             a、 得到方法對象

              Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);

//”service”,這個方法要傳入的參數有兩個,分別是HttpServletRequset和HttpServletResponse類型。

              b、調用方法

              m.invoke(obj,request,response);  --3.servlet的service方法被調用

//上面代碼的解釋參考前面,

5)當tomcat服務器停止或web應用重新部署,通過反射調用destroy方法

a、得到方法對象
Method m = clazz.getDeclareMethod(“destroy”,null);

b、 調用方法

m.invoke(obj,null); –4.servlet的destroy方法被調用
c、 用時序圖來演示servlet的生命週期

5) Servlet的自動加載

默認情況下,第一次訪問servlet的時候創建servlet對象。如果servlet的構造方法或init方法中執行了比較多的邏輯代碼,那麼導致用戶第一次訪問sevrlet的時候比較慢。

怎麼解決上面的說的加載慢的問題: 改變servlet創建對象的時機: 提前到加載web應用的時候!!!
在servlet的配置信息中,加上一個即可!!

<servlet>

    <servlet-name>LifeDemo</servlet-name>

    <servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>

    <!-- 讓servlet對象自動加載 -->

    <load-on-startup>1</load-on-startup>  注意: 整數值越大,創建優先級越低!!

  </servlet>

6) Servlet的多線程併發問題

注意: servlet對象在tomcat服務器是單實例多線程的。

因爲servlet是多線程的,所以當多個servlet的線程同時訪問了servlet的共享數據,如成員變量,可能會引發線程安全問題。
解決辦法:
1)把使用到共享數據的代碼塊進行同步(使用synchronized關鍵字進行同步)

2)建議在servlet類中儘量不要使用成員變量。如果確實要使用成員,必須同步。而且儘量縮小同步代碼塊的範圍。(哪裏使用到了成員變量,就同步哪裏!!),以避免因爲同步而導致併發效率降低。

Servlet學習:

HttpServletRequest 請求對象:獲取請求信息

HttpServletResponse 響應對象: 設置響應對象

ServletConfig對象 servlet配置對象

ServletContext對象; servlet的上下文對象

7) ServletConfig對象
a、 作用
ServletConfig對象: 主要是用於加載servlet的初始化參數。在一個web應用可以存在多個ServletConfig對象(一個Servlet對應一個ServletConfig對象)
b、 對象創建和得到

創建時機: 在創建完servlet對象之後,在調用init方法之前創建。
得到對象: 直接從有參數的init方法中得到!!!
c、 servlet的初始化參數配置

  <servlet>

    <servlet-name>ConfigDemo</servlet-name>

    <servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>

    <!-- 初始參數: 這些參數會在加載web應用的時候,封裝到ServletConfig對象中 -->

    <init-param>

        <param-name>path</param-name>

        <param-value>e:/b.txt</param-value>

    </init-param>

  </servlet>

注意: servlet的參數只能由當前的這個servlet獲取!!!!
ServletConfig的API:

java.lang.String getInitParameter(java.lang.String name) 根據參數名獲取參數值
java.util.Enumeration getInitParameterNames() 獲取所有參數
ServletContext getServletContext() 得到servlet上下文對象 java.lang.String getServletName() 得到servlet的名稱

8) ServletContext對象
a、 引入
ServletContext對象 ,叫做Servlet的上下文對象。表示一個當前的web應用環境。一個web應用中只有一 個ServletContext對象。
b、 對象創建和得到
創建時機:加載web應用時創建ServletContext對象。
得到對象: 從ServletConfig對象的getServletContext方法得到

我們設計:
創建ServletConfig對象

public void init( ServletConfig config,ServletContext context ){ 多了一個參數

得到ServletConfig對象

得到ServletContext對象;

}

Sun公司設計

1)創建ServletContext對象 ServletContext context = new ServletContext()
2)創建ServletConfig對象 ServetConfig config = new ServletConfig(); config.setServletContxt(context);
class ServletConfig{ ServletContext context;
public ServletContext getServletContxt(){
return contxt;
}
}
public void init( ServletConfig config ){
得到ServletConfig對象
從ServletConfig對象中得到ServletContext對象
SerlvetContext context = config.getServletContext();
}

9) ServletContext對象的核心API(作用)
java.lang.String getContextPath() –得到當前web應用的路徑
java.lang.String getInitParameter(java.lang.String name) –得到web應用的初始化參數
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) –域對象有關的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) –轉發(類似於重定向)
java.lang.String getRealPath(java.lang.String path) –得到web應用的資源文件
java.io.InputStream getResourceAsStream(java.lang.String path)

a、 得到web應用路徑

java.lang.String getContextPath() 用在請求重定向的資源名稱中
b、得到web應用的初始化參數(全局)
java.lang.String getInitParameter(java.lang.String name) –得到web應用的初始化參數
java.util.Enumeration getInitParameterNames()
web應用參數可以讓當前web應用的所有servlet獲取!!!
c、域對象有關的方法
域對象:作用是用於保存數據,獲取數據。可以在不同的動態資源之間共享數據。
案例:
ServletContext就是一個域對象!!!!

保存數據:void setAttribute(java.lang.String name, java.lang.Object object)
獲取數據: java.lang.Object getAttribute(java.lang.String name)
刪除數據: void removeAttribute(java.lang.String name)
ServletContext域對象:作用範圍在整個web應用中有效!!!
所有域對象:
HttpServletRequet 域對象 ServletContext域對象
HttpSession 域對象
PageContext域對象

d、 轉發

RequestDispatcher getRequestDispatcher(java.lang.String path)
1)轉發

    a)地址欄不會改變
b)轉發只能轉發到當前web應用內的資源
    c)可以在轉發過程中,可以把數據保存到request域對象中

2)重定向

    a)地址欄會改變,變成重定向到地址。

    b)重定向可以跳轉到當前web應用,或其他web應用,甚至是外部域名網站。

     c)不能再重定向的過程,把數據保存到request中。



   結論: 如果要使用request域對象進行數據共享,只能用轉發技術!!!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章