JSP是Java Server Page的縮寫,在傳統的HTML頁面中加入JSP標籤和java的程序片段就構成了JSP。JSP中腳本元素包括3類:聲明語句、腳本段和JSP表達式,在JSP頁面中需要通過特殊的約定來表示這些元素,在客戶端這些元素是不可見的,它們都是由服務器來執行。
聲明語句
聲明語句在JSP頁面中定義方法和變量,其聲明格式如下:
<%! 聲明變量或方法 %>
Eg1:<%! int count=100; %>
Eg2:<%! String getName() { return name;} %>
在頁面中通過聲明元素的方法和變量,在整個頁面內部都有效,它們是JSP頁面被轉換爲類文件後的方法和屬性,並且它們會被多個線程(即多個用戶)共享。也就是說,其中的任何一個線程對生命的變量或方法進行修改都會改變它們原來的狀態。它們的生命週期從創建開始,到服務器關閉後結束。
注:
- 聲明必須是完整的聲明語句,遵照Java語言的語法。
- 使用聲明語句的變量爲全局變量,也就是說,當有多個用戶在執行此JSP頁面時,將共享該變量。
- 在“<%”與“!”之間不要有空格。聲明的語法與在Java語言中聲明變量和方法是一樣的。
- 聲明只在當前JSP頁面中有效。
- 聲明不會在當前的輸入流中產生任何輸出。
Eg3:
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%!
int number =0;//聲明計數變量number
void add(){//該方法用來實現計數功能
number++;
}
%>
<%
this.add();//該腳本程序調用定義的計數方法
%>
本網頁的訪問次數是:<%=number %>次。
</body>
</html>
或者這樣寫:
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%!
int number =0;//聲明計數變量number
%>
本網頁的訪問次數是:<%=++number %>次。
</body>
</html>
【結果】
剛執行時,頁面顯示是1次;刷新頁面,次數逐漸增加;關閉Tomcat服務器重啓啓動執行,頁面再次顯示1次。(上面的代碼還要注意一下前綴加和後綴加哦,前綴加是先返回再做加法;後綴加是先做加法再返回。所以第二個代碼應該輸出“++number”)
腳本段
腳本段就是JSP代碼片段或腳本片段,嵌在“<%%>”標記中。在腳本段可以定義變量、調用方法和進行各種表達式運算,每行語句後面加入分號(因爲在<%%>裏面嵌入的Java代碼和我們一般的Java代碼沒有什麼區別,這和表達式是不同的)。使用JSP腳本元素可以將Java代碼嵌入到JSP頁面裏,這些Java代碼將出現在由當前JSP頁面生成的Servlet中,使JSP將靜態內容與動態內容分離出來。這種Java代碼在Web服務器響應請求時會運行。在腳本段周圍可以是原始的HTML或XML語句,在這些地方,代碼段可以創建條件執行代碼,或調用另一段代碼。
腳本段使用格式如下:
<% Java代碼 %>
Eg4:<%intcount=100;%>
<%%>是腳本段,它是在請求處理期間要執行的java代碼段。腳本段可以產生輸出,並把輸出發送到客戶端,也可以是一些流程控制語句。在腳本段中可以聲明本地變量,在後面的腳本段中一樣可以使用該變量。
Eg5:
<%@ page language="java" contentType="text/html;charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%!
//int number =0;//聲明計數變量number
%>
<%
//this.add();//該腳本程序調用定義的計數方法
int number =0;//聲明計數變量number
%>
本網頁的訪問次數是:<%=++number %>次。
</body>
</html>
【結果】
每次訪問都是1次,刷新網頁沒變化;關閉Tomcat服務器再重啓仍然沒變化。
<!% %>與<% %>的比較
二者的差異在於作用域和生存期:
①jsp聲明中創建的名字有類範圍的作用域和生存期
②jsp腳本中創建的名字有侷限於方法的作用域和生存期。
二者的作用域就像是java中在類中定義一個屬性A和在類的方法中定義一個屬性B,類中不能引用屬性B,但是在方法中可以引用屬性A。
二者的生存期:
①jsp聲明,例如:<%!int count=100;%><%=count++%>。 腳本中的變量生存期存在於第一個用戶延續到第二個用戶。。。。,如果第一個用戶第一次訪問時100,第二個用戶訪問就101,第三個用戶訪問時102,以此類推。。。如果服務器停止而重新啓動後,則count值就返回到100。
②jsp腳本,例如:<%int count=100;%><%=count++%>。 腳本中的變量生存期存在於每個用戶的訪問期間,所以每次用戶訪問都是100。
無論聲明和腳本放置的位置不同,jsp容器都是首先進行初始化聲明,再執行腳本的。
【總結】
①不能在腳本中定義方法,但可以在jsp聲明中定義自己的方法,因爲腳本程序是侷限於jspService方法中的,如果在jspservice方法中再次定義方法是不允許的。
②不能在jsp聲明中使用out等隱藏對象,因爲out等隱藏對象,是作用域jspservice方法中定義的。
③腳本中定義變量,不能在jsp聲明中引用此變量。
④如果變量定義在方法中,則不能在方法之前使用此變量。
⑤腳本的本質就是將代碼插入到Servlet的service()方法中。聲明的本質其實就是將聲明的變量加入到Servlet類(在任何方法之外),方法就成了Servlet()的方法。
【後臺原理】
利用<%!%>聲明的變量,在JSP容器轉換JSP頁面爲Servlet類時,將作該類的實例變量或者類變量(聲明時使用了static關鍵字),在多用戶併發訪問時,將導致線程安全的問題,除非你確認是單用戶訪問或者變量是隻讀的。(這裏不討論線程安全的問題)
而 <%%>,在JSP容器轉換JSP頁面爲Servlet類時,頁面中的代碼會按照代碼段中出現的次序,依次被轉換爲_jspService()方法中的代碼,在腳本段生命的變量,將作爲_jspService()方法中的本地變量,因此腳本段中的變量是線程安全的
表達式
JSP表達式用來把Java數據向頁面直接輸出信息,其使用格式如下:
<%=Java變量或返回值的方法名稱%>
Eg6:<%=newjava.util.Date()%> //通過JSP表達式實現Date類對象,並輸出當前的系統時間
Eg7:<%=a+b%> //輸出a+b的值
Eg8:<%=user.getName()%> //輸出getName()這個方法的返回值
表達式的本質:在將JSP頁面轉換成Servlet後,使用out.print()將表達式的值輸出。這樣如果user.getName()的返回值是"liky", 那麼實際上在servlet中就將轉換成out.print("liky");
注意:因此這裏要注意以下兩點:
①如果表達式是調用一個方法,那麼這個方法必須要有返回值,而不應是void。例如:void getName(),這樣的方法是不能被調用的。
②在方法的後面不能有分號。例如<%=getName();%>這是不允許的。
<%= %> 和 <% %>的比較
- <%= %>中的內容會被直接打印出來,且不允許多行和分號。而<% %>中間可以寫java代碼段,與java語法相同。
- <%= %> 會被解析成out.print();而<% %>中間的內容會直接解析成對應的代碼段。
Eg9:
對應的java文件代碼如下圖所示:
上圖中並沒有看到關於i的聲明,i在聲明標籤中會被聲明成一個全局變量,如下圖所示:
而且在servlet在服務器中是單實例,實例被創建要等到服務停掉纔會銷燬,而每次請求會執行其中的_jspService函數,這就意味如果用聲明腳本聲明瞭一個變量,那麼在所有的服務請求中都會是同一個變量。
部分參考於:
http://www.2cto.com/kf/201607/524648.html
http://blog.csdn.net/zzh19911025/article/details/45949797
http://blog.csdn.net/yinyuan1987/article/details/3099924