from:http://qing.weibo.com/tj/78edbfd833000h6o.html
一、歷史
JSP是Servlet的擴展,JSP沒出現之前,就已經出現了Servlet技術.Servlet是利用了"輸出流",動態的生成了HTML頁面。包括 每一個HTML標簽和所有的HTML頁面中出現的內容,簡單點說就是利用Servlet的輸出流將HTML標簽生成一個HTML頁面。由於時間長了 Servlet中包含了大量的HTML標簽、大量的靜態文本及格式等,導致了Servlet的開發效率非常低下.
這時候JSP誕生了,JSP彌補了這種情況,JSP通過在標准的THML頁面中嵌入JAVA代碼,使其靜態的部分無需JAVA程序控制,只有那些需要從數據庫讀取或需要動態生成的頁面內容,才使用JAVA腳本控制。
二、組成
JSP主要是由兩部分組成:
(1)靜態部分:標准的HTML標簽、靜態的頁面內容,這些內容與靜態HTML頁面相同.
(2)動態部分:Java程序控制的內容,這些內容由Java程序來動態生成。
下面是一個最簡單的一段jsp代碼:
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %> <html> <head> <title>歡迎</title> </head> <body> 歡迎學習Java JSP!現在時間是:<%out.println(new java.util.Date());%> </body> </html>
頁面中粗體字代碼放在<%和%>之間,表明這些是Java腳本,而不是靜態內容,通過這種方式就可以把Java代碼嵌入HTML頁面中,這就變成了動態的JSP頁面。從表面上來分析,JSP頁面已經不再需要Java類,似乎感覺完全脫離了Java面向對象的特征了,但是,實際上JSP是Servlet的一種特殊的形式,每一個JSP的頁面就是一個Servlet的實例。
為什么是Servlet實例?那是因為你的web項目中每一個JSP頁面,首先都會由Servlet容器生成對應的Servlet類.這個生成好的類放在C:\Program Files\Apache Software Foundation\Tomcat 6.0\work目錄下(注:這里是我自己默認的安裝的目錄)。如果你有過研究的話,你會發現,你部署完你的項目之后,當你啟動了Tomcat之后,你可以在Tomcat的work\Catalina\localhost\你項目名\org\apache\jsp目錄下找到index_jsp.class 和index_jsp.java這兩個文件.其實index_jsp.java是一個特殊的Java類,實際上就是一個Servlet類。
index_jsp.java 這個類間接的繼承了Servlet。仔細看下面的代碼:
//JSP頁面經過Tomcat編譯后默認的包
package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; //繼承HttpJspBase類,該類其實是Servlet的子類 public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.AnnotationProcessor _jsp_annotationprocessor; public Object getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext (getServletConfig().getServletContext()).getExpressionFactory(); _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache. AnnotationProcessor.class.getName()); } public void _jspDestroy() { } //用於響應用戶請求的方法 public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; //定義頁面輸出流 JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { //設置響應格式 response.setContentType("text/html; charset=gb2312"); 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("<!-- 表明這為一個JSP頁面 -->\r\n"); out.write("\r\n"); out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional //EN\">\r\n"); out.write("<HTML>\r\n"); out.write("<HEAD>\r\n"); out.write("<TITLE>第二個JSP頁面</TITLE>\r\n"); out.write("</HEAD>\r\n"); out.write("<BODY>\r\n"); out.write("<!-- 下面是Java腳本 -->\r\n"); //頁面中的循環,在此處循環輸出 for(int i = 0 ; i < 7; i ) { out.println("<font size='" i "'>"); out.write("\r\n"); out.write("Java的web世界!)</font>\r\n"); out.write("<br>\r\n"); } out.write("\r\n"); out.write("</BODY>\r\n"); out.write("</HTML>\r\n"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context. handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
上面的代碼全是WEB容器負責生成的。
三、工作原理
(1)當用戶訪問一個JSP頁面時,回想一個Servlet容器(Tomcat)發出請求;
(2)如果是第一次請求頁面,或頁面有所改動,則servlet容器首先要把JSP頁面(假設為test.jsp)轉化為Servlet代碼(test.java),再將其轉化為(test.class文件);因為這個過程(編譯)會耗費一定時間,所以第一次訪問或jsp文件有改動時,訪問時間有些長;
(3)JSP容器負責調用從JSP轉換來的servlet,這些servlet負責提供服務相應用戶請求(比如客戶端發送表單,要求servlet:formprocessor.java來處理,則容器會建立一個線程,調用formprocessor.java來處理該請求);如果用戶有多個請求,則容器會建立多個線程處理多個請求;
(4)容器執行字節碼文件(包括調用的servlet:formprocessor.java字節嗎),並將其結果返回到客戶端;(返回的最終方式是有servlet輸出html格式的文件流)
注釋:
JSP頁面必須要在JSP服務器內運行,如tomcat weblogic,jboss等等.(順便說一下,apache 和 tomcat是兩碼事兒,有不少人認為
apache就是tomcat,其實是錯誤的理解!~,tomcat只是apache中的一個子項目,apache是作為WEB應用服務器,而tomcat可以說是JSP或
Servlet的一個web容器);
JSP頁面的訪問者無須安裝任何客戶端,甚至不需要可以運行Java的運行環境,因為JSP頁面輸送到客戶端的是標准HTML頁面。