JSP 簡介#
JSP (Java Server Pages),其根本是一個簡化的 Servlet 設計,它實現了在 Java 中使用 HTML 標籤。JSP 是一種動態網頁技術標準,也是 JavaEE 的標準。JSP 和 Servlet 一樣,是在伺服器端執行的。JSP 是在 Servlet 技術發展之後為了讓開發者寫 HTML 標籤更方便而發展起來的技術,JSP 實際上就是 Servlet。
但是,人們通常把 Servlet 作為 Web 應用中的控制組件來使用,只負責響應請求產生數據,並把數據通過轉發技術帶給 JSP,而把 JSP 技術作為數據顯示模板來使用。這樣使程序結構更清晰,可讀性和可維護性更高。
常用動態網站開發技術#
JSP:Java 平台,安全性高,適合開發大型的,企業級的,分佈式的 Web 應用程序。如 Hadoop,電子銀行,12306 等
ASP.NET:.Net 平台,簡單易學。但是安全性以及跨平台型差。
PHP:簡單,高效,成本低開發周期端,特別適合中小型企業的 Web 應用開發。(LAMP: Linux+Apache+MySQL+PHP)
JSP 頁面元素構成#
JSP 指令#
JSP 指令 (directive) 是為 JSP 引擎設計的,它們並不直接產生任何可見輸出,而只是告訴引擎如何處理 JSP 頁面中的其餘部分。在 JSP2.0 規範中共定義了三個指令,基本語法格式為,<%@ 指令 屬性名 ="值" %>
,如果一個指令有多個屬性,這多個屬性可以寫在一個指令中,也可以分開寫。
-
page 指令:page 指令用於定義 JSP 頁面的各種屬性,無論指令出現在頁面中的什麼地方,它作用的都是整個 JSP 頁面,為了保持程序的可讀性和遵循良好的編程習慣,page 指令通常放在整個 JSP 頁面的起始位置,一個頁面可以有多個 page 指令。
<%@ page language="java" contentType="text/html,ISO-8859-1" import="java.util.*,java.sql.*,java.io.*" session="true|flase" buffer="none|8kb|sizekb" autoFlush="true|false" info="一段字符串內容" errorPage="relative_url" isErrorpage="true|false"%>
- language 指定 JSP 頁面使用的腳本語言,默認值為 java
- contentType 用來指定 JSP 頁面的文件類型和所採用的編碼方式,默認值為 “text/html,ISO-8859-1”
- import 通過該屬性來引用腳本語言中使用到的類文件,導入多個類或包用逗號分隔。 JSP 引擎自動導入 java.lang.;java.servlet.;javax.servlet.jsp.;javax.servlet.http.
- pageEncoding 指定 JSP 頁面的編碼方式,默認值為 “ISO-8859-1”
- session 用來說明是否創建 session 對象,默認為 true
- buffer 用來指定 out 對象是否創建 buffer 緩衝區,並指定緩衝區大小。默認為 8kb, none 表示不創建緩衝區。
- autoFlush 緩衝區是否自動刷新,默認為 true,如果為 false,緩衝區滿後不手動刷新會拋出異常。
- info 定義一個字符串常量,使用 getServletInfo 方法可以打印。
- errorPage 指定異常處理頁。也可以在 web.xml 中使用元素為整個 WEB 應用程序設置處理頁面,其中的子元素指定異常類的完全限定名,元素指定以 "/" 開頭的錯誤處理頁面的路徑。如果設置了某個 JSP 頁面的 errorPage 屬性,那麼在 web.xml 文件中的錯誤處理將不對該頁面起作用。
-
include 指令:用於引入其他 JSP 頁面,如果使用 include 指令引入了其他 JSP 頁面,那麼 JSP 引擎將把這兩個 JSP 翻譯成一個 Servlet,所以 include 指令引入通常也稱為靜態引入。
<%@ include file=“被包含組件的絕對URL或相對URL"%>
被引入的文件必須遵循 JSP 語法。被引入的文件可以是任意擴展名,即使其擴展名是 html,JSP 引擎也會按照處理 jsp 頁面的方式處理它裡面的內容,為了見名知意,JSP 規範建議使用.jspf (JSP fragments) 作為靜態引入文件的擴展名。由於使用 include 指明將會涉及到 2 個 JSP 頁面,並會把 JSP 翻譯成一個 Servlet,所以這兩個 JSP 頁面的指令不能衝突 (pageEncoding 和導包除外)。
- taglib 指令:使用標籤庫定義顯示自定義標籤,在 JSP 頁面中啟用定製行為。
表達式#
在 JSP 頁面中執行的表達式 <%=表達式%>
,注意表達式不以分號結束。例如,當前時間: <%= new java.util.Date() %>
腳本片段#
在 JSP 頁面中插入多行 java 代碼 <% Java代碼 %>
,JSP 引擎在翻譯 JSP 頁面時,會將 JSP 腳本片段中的 Java 代碼原封不動的放到 Servlet 的_jspServlet 方法中,所以,<% %>
中的 Java 代碼必須嚴格遵循 java 語法。
聲明#
在 JSP 頁面中定義變量或者方法 <%! Java代碼 %>
,聲明中的 Java 代碼被翻譯到_jspService 方法的外面,屬於類,所以可以聲明成員變量並初始化,也可以聲明方法或定義方法,同時還可以聲明靜態代碼塊。 JSP 隱式對象的作用範圍僅限於 Servlet 的_jspService 方法,所以在 JSP 聲明中不能使用這些隱式對象。
<%!
static {
System.out.println("loading Servlet!");
}
private int globalVar = 0;
public void jspInit() {
System.out.println("initializing jsp!");
}
%>
<%!
public void jspDestroy() {
System.out.println("destroying jsp!");
}
%>
註釋 (3 種方式)#
- HTML 註釋
- JSP 註釋:
<%--JSP註釋,客戶端不可見--%>
- JSP 腳本註釋: 即 java 註釋
//單行
,/*多行 */
靜態內容#
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>index.jsp page</title>
</head>
<body>
<h1>大家好</h1><hr>
<!-- 我是HTML註釋,在客戶端可見 -->
<%-- 我是JSP註釋,在客戶端不可見 --%>
<%!
String s = "張三";
//聲明了一個字符串變量
int add(int x,int y) {
//聲明了一個返回整型的函數,实现兩個整數的求和。
return x+y;
}
%>
<%
//單行註釋
/*多行註釋*/
out.println("大家好");
%>
<br>
你好,<%=s %><br>
x+y=<%=add(10,5) %><br>
</body>
</html>
JSP 運行原理及生命周期#
用戶第一次請求 Tomcat 會將 JSP 文件編程成一個 Servlet 的 java 文件,並將 java 文件編譯成 class 文件,載入到內存,生成文件在 Tomcat 的 work 目錄的對應項目文件夾。如果 JSP 頁面發生了修改,JSP 引擎會對其進行重新編譯並載入到內存,以方便用戶請求。注意,用戶第一次請求一個 JSP 頁面時,首先被執行的方法是構造方法。
_jspService () 方法被調用來處理客戶端的請求。對每一個請求,JSP 引擎創建一個線程來處理該請求。如果有多個客戶端同時請求該 JSP 文件,則 JSP 引擎會創建多個線程。每個客戶端請求對應一個線程。以多線程方式執行可以大大降低對系統資源的需求,提高系統的並發量及響應時間。但也要主要多線程的編程帶來的額同步問題,由於該 Servlet 始終駐於內存,所以響應是非常快的。
JSP 引擎在調用 JSP 對應的 jspServlet 時,會傳遞或創建 9 個與 web 開發相關的對象供 jspServlet 使用。 JSP 技術的設計者為便於開發人員在編寫 JSP 頁面時獲得這些 web 對象的引用,特意定義了 9 個相應的變量,開發人員在 JSP 頁面中通過這些變量就可以快速獲得這 9 大對象的引用。
JSP 9 個內置對象#
內置對象簡介#
JSP 內置對象是 Web 容器創建的一組對象,不使用 new 關鍵字就可以使用的內置對象。
四種作用域範圍#
- application_SCOPE: 作用於整個 Web 應用,多個用戶之間共享。
- session_SCOPE: 作用於整個 Web 應用,單個用戶之間共享。
- request_SCOPE: 作用於請求,轉發間請求共享。
- page_SCOPE: 作用於當前頁面,當前頁面可見。
out 對象#
緩衝區: Buffer,即內存中的一塊區域用來保存臨時數據。
out 對象: 是 JspWriter 類的實例,是向客戶端發送文本常用的對象,是通過調用 pageContext 對象的 getOut 方法返回的,其作用和用法與 ServletResponse.getWriter 方法返回的 PrintWriter 對象非常相似。JSP 頁面中的 out 隱式對象的類型為 JspWriter,JspWriter 相當於一種帶緩存功能的 PrintWriter,設置 JSP 頁面的 page 指令的 buffer 屬性可以調整它的緩存大小,甚至關閉它的緩存。當緩衝區滿足如下條件時才會寫入 Servlet 引擎提供的緩衝區:設置 page 指令的 buffer 屬性關閉了 out 對象的緩存功能;out 對象的緩衝區已滿。整個 JSP 頁面結束。
<%
out.println("aaa");
response.getWriter().write("bbb");
%>
"bbb會比aaa先輸出"
常用方法:
- void println (); 向客戶端打印字符串
- void clear (); 清除緩衝區的內容,如果在 flush 之後調用會拋出異常。
- void clearBuffer (); 清除緩衝區的內容,如果在 flush 之後調用不會拋出異常
- void flush (); 將緩衝區內容輸出到客戶端
- int getBufferSize (); 返回緩衝區以字節數的大小,如不設緩衝區則為 0
- int getRemaining (); 返回緩衝區還剩餘多少可用
- boolean isAutoFlush (); 返回緩衝區滿是,是自動清空還是拋出異常
- void close (); 關閉輸出流
request/response 對象#
表單的兩種提交方式
-
Get: 以明文的方式通過 URL 提交數據,數據在 URL 中可以看到。提交的數據最多不超過 2KB。安全性較低,但效率比 post 方式高。適合提交數據量不大,安全性高的數據。比如:搜索、查詢等功能。
-
Post:將用戶提交的信息封裝在 HTML header 內。適合提交數據量大,安全性高的用戶信息。比如:註冊、修改、上傳等功能。
request 對象#
客戶端的請求信息被封裝在 request 對象中,通過它才能了解到客戶端的需求,然後做出響應。它是 HttpServletRequest 類的實例。request 對象具有請求域,即完成客戶端的請求之前,該對象一直有效。
request 對象常用方法
- String getParameter (); 返回指定參數的參數值
- String [] getParameterValues (); 返回指定參數的所有值
- void setAttribute (); 存儲此請求中的屬性
- object getAttribute (); 返回指定屬性的屬性值
- String getContentType (); 得到請求體的 MIME 類型
- String getProtocol (); 返回請求用的協議及版本號
- String getServerName (); 返回接受請求的伺服器主機名
- int getServerPort (); 返回伺服器接受此請求的端口號
- String getCharacterEncoding (); 返回字符編碼方式
- void setContentEncoding (); 設置請求的字符編碼方式
- int getContentLength (); 返回請求體的長度(以字節數)
- String getRemoteAddr (); 返回發送此請求的客戶端 IP 地址
- String getRealPath (String path); 返回一個虛擬路徑的真實路徑或相對路徑的絕對路徑
- String getContextPath (); 返回上下文路徑,即項目的根目錄
中文亂碼問題:request.setCharacterEncoding("UTF-8");
URL 中中文亂碼問題:Tomcat的/conf/server.xml 的添加屬性
。
response 對象#
response 對象包含了響應客戶請求的有關信息,但在 JSP 中很少直接用到它。它是 HttpServletResponse 類的實例。response 對象具有頁面作用域,及訪問一個頁面時,該頁面內的 response 對象只能對這次訪問有效,其他的 response 對象對當前頁面無效。
response 對象常用方法
- String getCharacterEncoding (); 返回響應用的是何種字符編碼
- void setContentType (); 設置響應的 MIME 類型,一般為 "text/html, charset=UTF-8"
- PrintWriter getWriter (); 返回可以向客戶端輸出字符的一個對象 (“注意比較:PrintWriter 與內置 out 對象的區別,PrintWriter 對象的其輸出總是提前於內置 out 對象,或者在 out 中手動 flush”)
- sendRedirect (location); 重新定向客戶端的請求
請求重定向: 是客戶端行為,response。sendRedirect (), 從本質上將等同於兩次請求,前一次的請求對象不會保存,地址欄的 URL 地址會改變。
請求轉發: 是伺服器行為,request.getRequestDispatcher ().forward (); 是一次請求,轉發後請求對象會保存,地址欄的 URL 地址不會改變。
session 對象#
session 表示客戶端與伺服器的一次會話,Web 中的 session 指的是用戶在瀏覽某個網站時,從進入網站到瀏覽器關閉所經過的這段時間,也就是用戶瀏覽這個網站所花費的時間。
在伺服器的內存中,為不同的用戶保存著不同的 session。
session 對象是一個 JSP 內置的對象。
session 對象在第一個 JSP 頁面被裝載時自動創建,完成會話期管理。
從一個客戶打開瀏覽器並連接到伺服器開始,到客戶關閉瀏覽器離開這個伺服器結束,被稱為一個會話。
當一個客戶訪問一個伺服器時,可能會在伺服器的幾個頁面之間切換,伺服器應當通過某種辦法知道這是一個客戶,就需要 session 對象。
session 對象是 HttpSession 類的實例。
session 的常用方法
- long getCreationTime (); 返回 session 創建時間
- String getId (); 返回 session 創建時 JSP 引擎為它設的唯一 ID 號
- Object setAttribute (); 使用指定名稱將對象綁定到此會話
- Object getAttribute (); 返回與此會話中的指定名稱綁定在一起的對象,沒有返回 null
- String [] getValueNames (); 返回一個包含此 session 中所有可用屬性的數組
- int getMaxInactiveInterval (); 返回兩次請求間隔多長時間此 session 被取消(單位秒)
- void setMaxInactiveInterval (); 設置 session 存活時間。
session 的生命周期
- 創建:當客戶端第一次訪問某個 jsp 或者 Servlet 時,伺服器會為當前會話創建一個 SessionId,每次客戶端向服務端發送請求時,會將此 SessionId 攜帶過去,服務端會對此 SessionId 進行校驗。
- 活動:某次會話當中通過超鏈接打開的新頁面屬於同一次會話。只要當前會話頁面沒有全部關閉,重新打開新的瀏覽器窗口訪問同一項目資源時屬於同一次會話。除非本次會話的所有頁面都關閉後,在重新訪問某個 jsp 或者 Servlet 將會創建新的會話 (但此時原有會話還存在,這個 SessionId 仍然存在於服務端,只不過再也沒有客戶端會攜帶它然後教育服務端校驗,直到該會話超時。)。
- 銷毀:有三種銷毀方式
- 調用了 session.invalidate () 方法
- Session 過期(超時)可以在 web.xml 中配置 Session 超時的時間 1 單位是分鐘
- 伺服器重新啟動
application 對象#
application 對象實現了用戶間數據的共享,可存放全局變量。
application 開始於伺服器的啟動,終止於伺服器的關閉。
在用戶的前後連接或不同用戶之間的連接中,可以對 application 對象的同一屬性進行操作。
在任何地方對 application 對象屬性的操作,都將影響到其他用戶對此的訪問。
伺服器的啟動和關閉決定了 application 對象的生命。
application 對象是 ServletContext 類的實例。
application 的常用方法
- void setAttribute (); 使用指定名稱將對象綁定到此會話
- Object getAttribute (); 返回與此會話中的指定名稱綁定在一起的對象,如果沒有,返回 null
- Enumeration getAttributeNames (); 返回所有可用屬性名的枚舉
- String getServerInfo (); 返回 JSP (Servlet) 引擎名及版本號
page 對象#
page 對象就是指向當前 jsp 頁面本身,有點像類中的 this 指針,它是 java.lang.Object 類的實例。常用方法就是 Object 類的成員方法。
pageContext 對象#
pageContext 對象是 JSP 技術中最重要的一個對象,它代表 JSP 頁面的運行環境,這個對象不僅封裝了對其他 8 個隱式對象的引用,其自身還是一個域對象,可以用來保存數據。並且,這個對象還封裝了 web 開發中經常涉及到的一些常用操作,例如 include,forward 其他資源、檢索其他域對象中的屬性等。
pageContext 對象提供了對 jsp 頁面內所有的對象及名字空間的訪問。該對象可以訪問到本頁所在的 Session,也可以取本頁所在的 application 中的屬性值。該對象相當於頁面中所有功能的集大成者。該對象的本類名也叫 pageContext。
pageContext 的常用方法
- JspWriter getOut (); 返回當前客戶端響應被使用的 out 對象
- HttpSession getSession (); 返回當前頁中的 Session 對象
- Object getPage (); 返回當前頁的 page 對象
- ServletRequest getRequest (); 返回當前頁的 Request 對象
- ServletResponse getResponse (); 返回當前頁的 Response 對象
- void setAttribute (); 設置屬性及屬性值
- Object getAttribute (); 在指定範圍內取屬性的值
- int getAttributeScope (); 返回某屬性的作用範圍
- void forward (); 跳轉到另一個頁面,地址欄不變
- void include (); 包含另一個頁面,
- PageContext.APPLICATION_SCOPE 代表各個域的常量
- PageContext.SESSION_SCOPE
- PageContext.REQUEST_SCOPE
- PageContext.PAGE_SCOPE
- findAttribute (); 查找各個域中的屬性
Config 對象#
Config 對象是在一個 Servlet 初始化時,JSP 引擎向它傳遞信息用的,此信息包括 Servlet 初始化時所要用到的參數(通過屬性名和屬性值構成)以及伺服器的有關信息(通過傳遞一個 ServletContext 對象)
Config 的常用方法
- ServletContext getServletContext (); 返回含有伺服器信息的 ServletContext 對象
- String getInitParameter (); 返回初始化參數的值
- Enumeration getInitparameterNames (); 返回 Servlet 初始化所需所有參數的枚舉
Exception 對象#
Exception 對象是一個異常對象,當一個頁面在運行過程中發生了異常,就產生這個對象。如果一個 jsp 頁面要應用此對象,就必須報 isErrorPage 設為 true,否則無法編譯。它實際上是 java.lang.Throwable 的對象。頁面要想在有異常時得到處理,就要指定異常處理頁 <% page errorPage=“exception.jsp”%>
exception 的常用方法
- String getMessage (); 返回描述異常的消息
- String toString (); 返回關於異常的簡短描述消息
- void printStackTrace (); 顯示異常及其棧軌跡
- Throwable fillInStackTrace (); 重寫異常的執行棧軌跡
JSP 動作標籤#
-
JSP 動作元素 (action elements): 動作元素為請求處理階段提供信息。動作元素遵循 XML 元素的語法,有一個包含元素名的開始標籤,可以有屬性、可選的內容、與開始標籤匹配的結束標籤。
JSP 標籤也稱之為 JSP Action(JSP 動作)元素,它用於在 JSP 頁面中提供業務邏輯功能,避免在 JSP 頁面中直接編寫 java 代碼,造成 jsp 頁面難以維護。 -
JSP 動作元素包含五大類
- 與存儲 JavaBean 有關的:jsp, jsp, jsp.
- JSP1.2 規範就有的 6 個基本動作元素:jsp, jsp, jsp, jsp, jsp, jsp.
- JSP2.0 新增加,主要與 JSP Document 有關的 6 個動作元素:jsp, jsp, jsp, jsp, jsp, jsp.
- JSP2.0 新增加,主要用於動態生成 XML 元素標籤的值,包括 3 個動作:jsp, jsp, jsp.
- JSP2.0 新增加,只要用在 Tag File 中:jsp, jsp.
-
JSP 常用標籤
-
include: 該標籤用於把另外一個資源的輸出內容插入進當前 JSP 頁面的輸出內容中,這種在 JSP 頁面執行時的引入方式稱之為動態引入。
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
。flush 屬性指定在插入其他資源的輸出內容時,是否先將當前 JSP 頁面的已輸出的內容刷新到客戶端。 -
jsp與include指令比較: jsp標籤是動態引入, jsp標籤涉及到的 2 個 JSP 頁面會被翻譯成 2 個 servlet,這 2 個 servlet 的內容在執行時進行合併。而 include 指令是靜態引入,涉及到的 2 個 JSP 頁面會被翻譯成一個 servlet,其內容是在源文件級別進行合併。不管是 jsp標籤,還是 include 指令,它們都會把兩個 JSP 頁面內容合併輸出,所以這兩個頁面不要出現重複的 HTML 全局架構標籤,否則輸出給客戶端的內容將會是一個格式混亂的 HTML 文檔。但 include 指令要比 jsp標籤效率高些。可以從下面的表格中更直觀的看到兩者的區別.
include jsp 語法格式 <%@ include file=“…” %> < jsp page=“…” > 發生作用的時間 頁面轉換期間 請求期間 包含的內容 文件的實際內容 頁面的輸出 轉換成的 servlet 主頁面和包含頁面轉換成一個 Servlet 主頁面和包含頁面轉換為獨立的 Servlet 編譯時間 較慢 - 資源必須被解析 較快 執行時間 稍快 較慢 - 每次資源必須被解析 -
jsp: 該標籤用於把請求轉發給另外一個資源。<jsp page=“relativeURL | <%=expression%>” />。等同於 request。getRequestDispatcher (“/url”).forward (request,response)。即執行伺服器內部跳轉操作。
-
jsp: 當使用 jsp和 jsp標籤引入或將請求轉發給其它資源時,可以使用 jsp標籤向這個資源傳遞參數。
-
<jsp:include page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>"/>
</jsp:include>
可以使用多個<jsp:param>標籤來傳遞多個參數。
- 映射 JSP
映射 JSP 就是將一個 JSP 映射成其他任意形式的 URL,在 web.xml 文件配置
<servlet>
<servlet-name>SimpleJspServlet</servlet-name>
<jsp-file>/jsp/simple.jsp</jsp-file>
<load-on-startup>1</load-on-startup >
</servlet>
……
<servlet-mapping>
<servlet-name>SimpleJspServlet</servlet-name>
<url-pattern>/xxx/yyy.html</url-pattern>
</servlet-mapping>
JavaBeans#
-
Javabean 簡介
Javabeans 就是符合某種特定規範的 Java 類。使用 Javabeans 的好處是解決代碼重複編寫,減少代碼冗餘,功能區分明確,提高了代碼的可維護性。
-
Javabean 設計原則
必須是共有類;
必須包含一個無參的共有構造方法;
所有屬性必須私有;
使用 getter 和 setter 訪問器對屬性訪問封裝。public class Book { //一個符合要求的Javabean類 private String bookName; private String author; private double price; public Book() { } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } }
-
JSP 中如何使用 Javabean
第一種方式:像使用普通 java 類一樣,創建 javabean 實例。
第二種方式:在 JSP 頁面中通常使用 jsp 動作標籤使用 javabean。 -
scope
作用:在 jsp 頁面中實例化或者在指定範圍內使用 javabean
<jsp:useBean id="標識符" class="java類名" scope="作用範圍"/> <!-- scope默認為page。 -->
-
property
作用:給已經實例化的 Javabean 對象的屬性賦值,一共有四種形式:
<jsp:setProperty name="Javabean實例名" property="*"/>(跟表單關聯)
<jsp:setProperty name="Javabean實例名" property="Javabean屬性名"/>(跟表單關聯)
<jsp:setProperty name="Javabean實例名" property="Javabean屬性名" value="BeanValue"/>(手工設置)
<jsp:setProperty name="Javabean實例名" property="propertyName" param="request對象中的參數名"/>(跟request參數關聯)通過url地址傳遞的參數
- name
作用:獲取指定 Javabean 對象的屬性值。
<jsp:getProperty name="Javabean實例名" property="屬性名"/>
-
Javabean 的四個作用域範圍
使用 useBeans 的 scope 屬性可以用來指定 javabean 的作用範圍。
page:僅在當前頁面有效
request:可以通過 request.getAttribute 方法取得 JavaBean 對象
session:可以通過 session.getAttribute 方法取得 JavaBean 對象
application:可以通過 application.getAttribute 方法取得 JavaBean 對象