JSP:
JSP的生命周期指從創建到銷毀的整個過程。分為以下幾個階段:
1:編譯階段:servlet引擎編譯servlet源文件,生成servlet類。當瀏覽器請求JSP頁面時,JSP引擎會首先去檢查是否需要編譯這個文件。如果之前沒有被編譯過或者編譯后被更改過,則編譯這個JSP文件。編譯過程包含三個步驟:解析JSP文件--將JSP轉換為servlet--編譯servlet。
2:初始化階段:加載與JSP對應的servlet類,創建其實例並調用初始化方法。容器載入JSP文件后,會首先調用jspInit()方法。次方法可以重寫,一般情況寫程序只初始化一次,通常情況下可以在此方法中初始化數據庫連接、打開文件和創建查詢列表。
3:執行階段:調用與JSP對應的servlet實例的服務方法。當JSP網頁初始化完成后,JSP引擎會調用_jspService()方法。此方法需要一個HttpServletRequest對象和一個HttpServletResponse對象作為參數。_jspService()方法在每個request中被調用一次並且負責產生與之對應的response對象,別且還負責產生HTTP方法對應的回應。
4:調用JSP對應的servlet實例的銷毀方法,然后銷毀servlet實例。jspDestroy()負責執行JSP網頁從容器中的清理。涉及到的工作為釋放數據庫連接、關閉文件夾等等。
JSP的生命周期也能這樣描述:
Jsp頁必須轉換成Servlet,才能對請求進行服務,因此Jsp的底層完全是Servlet。這樣看來Jsp的生命周期就包括六個階段:轉換、編譯、加載並實例化、jspInit()調用(即初始化)、_jspService()調用(即請求處理)、jspDestroy()調用(即銷毀)。
轉換:就是web容器將Jsp文件轉換成一個包含了Servlet類定義的java源文件。
編譯:把在轉換階段創建的java源文件編譯成類文件。
Jsp生命周期其他的四個階段跟Servlet生命周期相同。
現在來具體講一下:
前一部分:
1.創建:就是創建一個JSP源文件
2.部署:將JSP安裝到服務器上(JaveEE服務器或單機運行的JSP服務器)
3.解釋和編譯:將JSP源文件解釋成java源代碼文件,然后將該源文件編譯成可在服務器上運行的java類,這個類成為JSP頁面的實現類。(這一步可能在以后多個地方都會遇到)
后一部分:
1.裝載和實例化:前提是完成了前一部分的幾步得到了一個實現類。服務器端會為JSP頁面查找已有的實現類,如果沒有,就把這個實現類載入JVM中;載入JVM后就立刻產生一個該類的實例,或者在第一次請求時執行。
2.初始化:初始化JSP頁面對象。如果你希望在初始化期間執行某些代碼,那么你可以向頁面中增加一個初始化方法(method),在初始化的時候就會調用該方法。
3.請求處理:由頁面對象響應客戶端的請求。需要注意的是,單個對象實例將處理所有的請求。在執行完處理之后,服務器將一個響應(response)返回給客戶端。這個響應完全是由HTML標簽和其他數據構成的,並不會把任何Java源碼返回給客戶端。
4.生命周期終止:服務器不再把客戶端的請求發給JSP。在所有的請求處理完成之后,會釋放掉這個類的所有實例。一般這種情況會發生在服務器關閉的時候,但是也有其他的可能性,比如服務器需要保存資源、檢測到有JSP文件更新,或者由於其他某些原因需要終止實例等情況。如果想讓代碼執行清除工作,那么可以實現一個方法,並且在這個類實例釋放之前調用該方法
如下圖所示的是servlet的生命周期和JSP非常的相似:
下面來測試一下JSP實現這些生命周期,在left.jsp頁面如下寫法:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>life.jsp</title> </head> <body> <%! private int initVar=0; private int serviceVar=0; private int destroyVar=0; %> <%! public void jspInit(){ initVar++; System.out.println("jspInit(): JSP被初始化了"+initVar+"次"); } public void jspDestroy(){ destroyVar++; System.out.println("jspDestroy(): JSP被銷毀了"+destroyVar+"次"); } %> <% serviceVar++; System.out.println("_jspService(): JSP共響應了"+serviceVar+"次請求"); String content1="初始化次數 : "+initVar; String content2="響應客戶請求次數 : "+serviceVar; String content3="銷毀次數 : "+destroyVar; %> <p><%=content1 %></p> <p><%=content2 %></p> <p><%=content3 %></p> </body> </html>
效果如下:
然后打開工作空間的生成的java文件:“\workspace_web_test\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\webtest1\org\apache\jsp\life_jsp.java”
會發現如下結構:
/* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat/7.0.68 * Generated at: 2016-12-14 13:18:33 UTC * Note: The last modified time of this file was set to * the last modified time of the source file after * generation to assist with modification tracking. */ package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class life_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private int initVar=0; private int serviceVar=0; private int destroyVar=0; public void jspInit(){ initVar++; System.out.println("jspInit(): JSP被初始化了"+initVar+"次"); } public void jspDestroy(){ destroyVar++; System.out.println("jspDestroy(): JSP被銷毀了"+destroyVar+"次"); } private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private volatile javax.el.ExpressionFactory _el_expressionfactory; private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public javax.el.ExpressionFactory _jsp_getExpressionFactory() { if (_el_expressionfactory == null) { synchronized (this) { if (_el_expressionfactory == null) { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); } } } return _el_expressionfactory; } public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() { if (_jsp_instancemanager == null) { synchronized (this) { if (_jsp_instancemanager == null) { _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } } } return _jsp_instancemanager; } public void _jspInit() { } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write("<title>life.jsp</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write("\r\n"); out.write("\r\n"); out.write(" \r\n"); out.write("\r\n"); out.write("\r\n"); serviceVar++; System.out.println("_jspService(): JSP共響應了"+serviceVar+"次請求"); String content1="初始化次數 : "+initVar; String content2="響應客戶請求次數 : "+serviceVar; String content3="銷毀次數 : "+destroyVar; out.write("\r\n"); out.write("<p>"); out.print(content1 ); out.write("</p>\r\n"); out.write("<p>"); out.print(content2 ); out.write("</p>\r\n"); out.write("<p>"); out.print(content3 ); out.write("</p>\r\n"); out.write("\r\n"); out.write("</body>\r\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
selevt:
1.實例化一個selevt
2.初始化 init()
3.執行service()方法 ,來處理請求
4.根據請求調用doget()或者doPost()方法
5.銷毀selevt : destroy()