【菜鳥學Java】6:JSP的基本原理
在上篇博文中介紹了JavaWeb開發中比較基礎也是比較經典的Servlet技術,同時也在文章的結尾點出了Servlet技術所帶來的問題,那就是由於包括大量的HTML標籤,大量的靜態文字及格式等,導致Servlet的開發效率極為低下。所有的表現邏輯,包括佈局、色彩及影像等,都必須耦合在Java程式碼中,這的確讓人覺得非常糟糕。
JSP的出現彌補了這種不足,JSP通過在標準的HTML頁面中嵌入Java程式碼,其靜態的部分無須Java程式控制,只有那些需要從資料庫讀取或者需要動態生成的頁面內容,才使用Java指令碼控制。從本質上來說,JSP也是Servlet,當使用者向指定的Servlet傳送請求時,Servlet利用輸出流動態生成HTML頁面,包括每一個靜態的HTML標籤和所有在HTML頁面中出現的內容。
JSP頁面的組成部分:
#靜態部分:標準的HTML標籤、靜態的頁面內容,這些內容與靜態HTML頁面相同。
#動態部分:受Java程式控制的內容,這些內容由Java指令碼動態生成。
下面我們來看一個最簡單的JSP頁面程式碼。
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<html>
<head>
<title>歡迎</title>
</head>
<body>
尊敬的使用者:您好!<br>
當前時間是:<br>
<% out.println(new java.util.Date());%>
</body>
</html>
上面的程式碼中,使用<%……%>符號包起來的內容,稱之為Java指令碼,這就是所謂的動態內容,通過這種方式可以把Java程式碼嵌入在HTML頁面中,這樣就成了動態的JSP頁面。我們在瀏覽器中訪問改頁面,可以看到如下頁面:
從表面上看,JSP頁面似乎已經不再需要Java類,好像完全脫離了Java物件導向的核心思想。事實上,JSP的本質依然是Servlet,這個在上文中已經提到,這裡詳細闡述一下。
其實每個JSP頁面就是一個Servlet例項——JSP頁面由系統編譯成Servlet,Servlet再負責響應使用者的請求。也就是說,JSP其實也是Servlet的一種簡化,使用JSP時,其實還是在使用Servlet,因為Web應用中的每個JSP頁面都會由Servlet容器生成對應的Servlet。對於Tomcat而言,JSP頁面生成的Servlet放在work路徑對應的Web應用下。
我們開啟Tomcat的檔案路徑,來檢視一下上面的JSP頁面所對應的類檔案和Java程式碼檔案,如下圖所示:
開啟welcome_jsp.java檔案,我們來看看它的程式碼是什麼樣的:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.42
* Generated at: 2015-12-17 08:33:01 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 welcome_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
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 javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
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=GBK");
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("<html>\r\n");
out.write("\t<head>\r\n");
out.write("\t\t<title>歡迎</title>\r\n");
out.write("\t</head>\r\n");
out.write("\t<body>\r\n");
out.write("\t\t尊敬的使用者:您好!<br>\r\n");
out.write("\t\t當前時間是:<br>\r\n");
out.write("\t\t");
out.println(new java.util.Date());
out.write("\r\n");
out.write("\r\n");
out.write("\t</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 { 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);
}
}
}
對於初學者來說,看到上面的Java類可能有點懵,這是什麼玩意啊?其實這就是一個Servlet類的原始碼,該Java類主要包含三個方法:
#init():初始化JSP/Servlet的方法。
#destroy():銷燬JSP/Servlet之前的方法。
#service():對使用者請求生成響應的方法。
即使不瞭解,也沒關係,這不影響我們開發自己JSP頁面,因為編譯的工作是由Web容器完成的。比如我們使用Tomcat就是一個Web容器。
小結一下:
關於JSP的工作原理,我們先來看一張圖,這是從網上找的,我覺得還不錯,可能對大家的理解有幫助。
綜上所述,我們可以得到幾個結論:
1JSP檔案必須在JSP伺服器內才可以執行
2JSP檔案必須生成Servlet才可以被執行
3每個JSP頁面的第一個訪問者的響應速度會很慢,因為這個使用者需要等待JSP被編譯成Servlet。
4JSP頁面的訪問者無需安裝任何客戶端,甚至不需要可以執行Java的執行環境,因為JSP頁面輸送到客戶端的是標準的HTML頁面,你有個瀏覽器就夠了。
JSP技術的出現,大大的提高了Java動態網站的開發效率,所以得到了廣大動態網站開發人士的青睞。
相關文章
- 【菜鳥學Java】7:JSP的基本語法JavaJS
- 菜鳥學Java(四)——JSP內建物件JavaJS物件
- 菜鳥學Java(五)——JSP內建物件之requestJavaJS物件
- 菜鳥學Java(十七)——Jboss瘦身Java
- 菜鳥學Java(十八)——異常Java
- 菜鳥學Java(九)——Servlet的基本配置JavaServlet
- 菜鳥學Java(十六)——Jboss簡介Java
- 菜鳥學Java(十一)——GET與POSTJava
- 【菜鳥學Java】11:Session技術JavaSession
- 【菜鳥學Java】10:Cookie技術JavaCookie
- 【菜鳥學Java】4:Servlet 技術JavaServlet
- 菜鳥學Java(十四)——Java反射機制(一)Java反射
- 菜鳥學Java(十五)——Java反射機制(二)Java反射
- 菜鳥學Java(十)——分頁查詢Java
- IT菜鳥的學習生活
- java菜鳥入門Java
- 菜鳥初學Java的備忘錄(二) (轉)Java
- 菜鳥初學Java的備忘錄(五) (轉)Java
- 菜鳥初學Java的備忘錄(八) (轉)Java
- 菜鳥初學Java的備忘錄(七) (轉)Java
- 菜鳥初學Java的備忘錄(九) (轉)Java
- 菜鳥初學Java的備忘錄(四) (轉)Java
- 菜鳥初學Java的備忘錄(六) (轉)Java
- 菜鳥初學Java的備忘錄(十) (轉)Java
- 菜鳥初學Java的備忘錄(一) (轉)Java
- 菜鳥初學Java的備忘錄(三) (轉)Java
- 【菜鳥學Java】15:JSP技術中的Model1和Model2開發模式JavaJS模式
- 菜鳥學Java(二十三)——Java記憶體分析Java記憶體
- 【菜鳥學Java】2:初識J2EEJava
- 菜鳥學Java(六)——簡單驗證碼生成(Java版)Java
- 菜鳥的資訊保安學習之路
- 菜鳥學習寫的Ioc工具
- Java菜鳥到大牛學習路線培訓教程Java
- 菜鳥學Java(二十二)——重新認識泛型Java泛型
- 【菜鳥學Java】5:“徒手”建立一個Web應用JavaWeb
- 跟著菜鳥學pythonPython
- 菜鳥學習SQL注射(轉)SQL
- 菜鳥學Java(三)——JSTL標籤之核心標籤JavaJS