一、JSP機制概述
可以把執行JSP頁面的執行分成兩個階段,一個是轉譯階段,一個是要求階段。
轉譯階段:JSP頁面轉換成Servlet類。
要求階段:Servlet類執行,將響應結果發送至用戶端。
1.使用者(客戶機)訪問響應的JSP頁面,如http://localhost:8080/Prj_test/ch02/HelloJSP.jsp。
2.伺服器找到相應的JSP頁面。
3.伺服器將JSP轉譯成Servlet的原始碼。
4.伺服器將Servlet原始碼編譯為class檔案。
5.伺服器將class檔案載入到記憶體並執行。
6.伺服器講class檔案執行後產生HTML代碼發送給客戶機,客戶機瀏覽器根據響應的HTML代碼進行顯示。
如果該JSP頁面為第一次執行,那麼會經過這兩個階段,而如果不是第一次執行,那麼將只會執行要求階段。這也是為什麼第二次執行JSP頁面時明顯比第一次執行要要快的原因。
如果修改了JSP頁面,那麼伺服器將發現到該修改,並重新執行轉譯階段和要求階段。這也是為什麼修改頁面後訪問速度變慢的原因。
jsp執行過程流程圖:
1、jsp引擎
JSP引擎實際上要把JSP標籤、JSP頁中的Java代碼甚至連同靜態HTML內容都轉換為大塊的Java代碼。這些代碼塊被JSP引擎組織到使用者看不到的Java servlet中去,然後servlet自動把JVM(java虛擬機器)編譯成Java位元組碼。這樣,當網站的訪問者請求一個JSP頁時,在他不知道的情況下,一個已經產生的、先行編譯過的servlet實際上將完成所有的工作。非常隱蔽-而又高效。因為servlet是編譯過的,所以網頁中的JSP代碼不需要在每次請求該頁時被解釋一遍。JSP引擎只需在servlet代碼最後被修改後編譯一次,然後這個編譯過的servlet就可以被執行了。由於是JSP引擎自動產生並編譯servlet,不用程式員動手編譯代碼,所以JSP能帶給你高效的效能和快速開發所需的靈活性。
2、web容器和servlet容器
servlet容器的主要任務是管理servlet的生命週期。web容器更準確的說應該叫web伺服器,它是來管理和部署web應用的。還有一種伺服器叫做應用伺服器,它的功能比web伺服器要強大的多,因為它可以部署EJB應用,可以實現容器管理的事務,一般的應用伺服器有weblogic和websphere等,它們都是商務服務器,功能強大但都是收費的。web容器最典型的就是tomcat了,Tomcat是web容器也是servlet容器
2、jsp工作原理當web容器(tomcat、jboss等等)接收到使用者的第一個jsp頁面請求時,jsp引擎將這個jsp頁面轉換為java原始碼(servlet類),在轉換過程中,如果發現jsp檔案有任何的語法錯誤,轉換過程將終止,並向伺服器和用戶端輸出錯誤資訊,如果轉換成功,然後jsp引擎用javac編譯java原始碼產生class檔案,然後web容器載入class檔案並從此建立一個新的servlet對象進行執行個體化,當 Servlet 類執行個體化後,容器載入 jsinit,以通知 servlet 它已進入服務行列。init 方法必須被載入,Servelt 才能接收和請求。假如要載入資料庫驅動程式、初始化一些值等等,程式員可以重寫這個方法。在其他情況下,這個方法一般為空白,jspInit()方法在servlet的生命週期中只被執行一次。然後jspService()方法被調用來處理用戶端的請求。容器建立一個響應文檔,次文檔發送給使用者,如幹時間後,使用者再次訪問這個j請求這個jsp時,容器回再次建立響應一個文檔,直到容器卸載了這個class檔案,當使用者卸載了這個class檔案後,再次訪問時,jsp引擎並不重新轉換和編譯這個jsp檔案,而是對它進行重新初始化,並建立一個響應文檔,返回給用戶端。對每一個請求,web容器建立一個新的線程來處理該請求。如果有多個用戶端同時請求該JSP檔案,則JSP引擎會建立多個線程。每個用戶端請求對應一個線程。以多線程方式執行可大大降低對系統的資源需求,提高系統的並發量及回應時間.但應該注意多線程的編程限制,由於該servlet始終駐於記憶體,所以響應是非常快的。如果.jsp檔案被修改了,伺服器將根據設定決定是否對該檔案重新編譯,如果需要重新編譯,則將編譯結果取代記憶體中的servlet,並繼續上述處理過程。如果在任何時候如果由於系統資源不足的原因,web容器將以某種不確定的方式將servlet從記憶體中移去。當這種情況發生時jspDestroy()方法首先被調用, 然後servlet執行個體便被標記加入"垃圾收集"處理。
3、jsp指令碼與聲明的差異 Jsp代碼
- <%!int count=100;%>--------jsp聲明
- <%int count=100;%>---------jsp指令碼
<%!int count=100;%>--------jsp聲明<%int count=100;%>---------jsp指令碼
二者的差異在於範圍和生存期,
(1)、jsp聲明中建立的名字有類範圍的範圍和生存期
(2)、jsp指令碼中建立的名字有局限於方法的範圍和生存期。
二者的範圍就像是java中在類中定義一個屬性A和在類的方法中定義一個屬性B,
類中不能引用屬性B,但是在方法中可以引用屬性A,
二者的生存期:
jsp聲明,例如:<%!int count=100;%><%=count++%>
指令碼中的變數生存期存在於第一個使用者延續到第二個使用者。。。。,如果第一個使用者第一次訪問時100,第二個使用者訪問就101,第三個使用者訪問時102,以此類推。。。如果伺服器停止而重新啟動後,則count值就返回到100,
jsp指令碼,例如:<%int count=100;%><%=count++%>
指令碼中的變數生存期存在於每個使用者的訪問期間,所以沒有使用者訪問都是100
無論聲明和指令碼放置的位置不同,jsp容器都是首先進行初始化聲明,再執行指令碼的。
總結:
(1)、不能在指令碼中定義方法,但可以再jsp聲明中定義自己的方法,因為指令碼程式是局限於jspService方法中的,如果在jspservice方法中再次定義方法是不允許的。
(2)、不能在jso聲明中使用out等隱藏對象,因為out等隱藏對象,是範圍jspservice方法中定義的。
(3)、指令碼中定義變數,不能在jsp聲明中引用此變數。
(4)、如果變數定義在方法中,則不能在方法之前使用此變數。